데이터 · 13
목록 고치기
있는지 묻기, 빼기, 뒤집기, 자리 바꾸기, 같은 값으로 채우기, 복사.
목록은 만든 뒤에도 값을 빼고 순서를 바꿀 수 있어요.
아래 예제는 카드 목록을 복사해 두고, 수 하나가 있는지 물어서 있으면 빼고, 맨 앞 카드를 빼고, 뒤집고, 앞의 두 장을 맞바꿔요.
그리고 고친 목록, 복사해 둔 처음 목록, 0으로 채운 새 목록을 찍어요.
n = int(input())cards = list(map(int, input().split()))x = int(input())original = cards.copy() # 복사해 둬요if x in cards: print("yes") cards.remove(x) # 값으로 빼기: 처음 나오는 하나만else: print("no")cards.pop(0) # 자리로 빼기: 0번cards.reverse()cards[0], cards[1] = cards[1], cards[0] # 자리 바꾸기blank = [0] * len(cards) # 0으로 채운 새 목록print(*cards)print(*original)print(*blank)const lines = require("fs").readFileSync(0, "utf8").trim().split("\n");const cards = lines[1].trim().split(/\s+/).map(Number);const x = Number(lines[2]);const original = [...cards]; // 복사해 둬요if (cards.includes(x)) { console.log("yes"); cards.splice(cards.indexOf(x), 1); // 값으로 빼기: 자리를 찾아서 하나만} else { console.log("no");}cards.splice(0, 1); // 자리로 빼기: 0번cards.reverse();[cards[0], cards[1]] = [cards[1], cards[0]]; // 자리 바꾸기const blank = new Array(cards.length).fill(0); // 0으로 채운 새 목록console.log(cards.join(" "));console.log(original.join(" "));console.log(blank.join(" "));import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").trim().split("\n");const cards: number[] = lines[1].trim().split(/\s+/).map(Number);const x: number = Number(lines[2]);const original: number[] = [...cards]; // 복사해 둬요if (cards.includes(x)) { console.log("yes"); cards.splice(cards.indexOf(x), 1); // 값으로 빼기: 자리를 찾아서 하나만} else { console.log("no");}cards.splice(0, 1); // 자리로 빼기: 0번cards.reverse();[cards[0], cards[1]] = [cards[1], cards[0]]; // 자리 바꾸기const blank: number[] = new Array<number>(cards.length).fill(0); // 0으로 채운 새 목록console.log(cards.join(" "));console.log(original.join(" "));console.log(blank.join(" "));import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.Scanner; public class Main { static void show(List<Integer> list) { StringBuilder line = new StringBuilder(); for (int i = 0; i < list.size(); i++) line.append(i > 0 ? " " : "").append(list.get(i)); System.out.println(line); } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); List<Integer> cards = new ArrayList<>(); for (int i = 0; i < n; i++) cards.add(sc.nextInt()); int x = sc.nextInt(); List<Integer> original = new ArrayList<>(cards); // 복사해 둬요 if (cards.contains(x)) { System.out.println("yes"); cards.remove(Integer.valueOf(x)); // 값으로 빼기: 처음 나오는 하나만 } else { System.out.println("no"); } cards.remove(0); // 자리로 빼기: 0번 Collections.reverse(cards); Collections.swap(cards, 0, 1); // 자리 바꾸기 List<Integer> blank = new ArrayList<>(Collections.nCopies(cards.size(), 0)); // 0으로 채운 새 목록 show(cards); show(original); show(blank); }}using System;using System.Collections.Generic;using System.Linq; class Program{ static void Main() { int n = int.Parse(Console.ReadLine()); List<int> cards = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(); int x = int.Parse(Console.ReadLine()); List<int> original = new List<int>(cards); // 복사해 둬요 if (cards.Contains(x)) { Console.WriteLine("yes"); cards.Remove(x); // 값으로 빼기: 처음 나오는 하나만 } else { Console.WriteLine("no"); } cards.RemoveAt(0); // 자리로 빼기: 0번 cards.Reverse(); (cards[0], cards[1]) = (cards[1], cards[0]); // 자리 바꾸기 List<int> blank = Enumerable.Repeat(0, cards.Count).ToList(); // 0으로 채운 새 목록 Console.WriteLine(string.Join(" ", cards)); Console.WriteLine(string.Join(" ", original)); Console.WriteLine(string.Join(" ", blank)); }}#include <algorithm>#include <iostream>#include <vector> void show(const std::vector<int>& list) { for (size_t i = 0; i < list.size(); i++) std::cout << (i > 0 ? " " : "") << list[i]; std::cout << '\n';} int main() { int n, x; std::cin >> n; std::vector<int> cards(n); for (int& c : cards) std::cin >> c; std::cin >> x; std::vector<int> original = cards; // 복사해 둬요(vector는 대입하면 복사) auto it = std::find(cards.begin(), cards.end(), x); if (it != cards.end()) { std::cout << "yes\n"; cards.erase(it); // 값으로 빼기: 찾은 자리 하나만 } else { std::cout << "no\n"; } cards.erase(cards.begin()); // 자리로 빼기: 0번 std::reverse(cards.begin(), cards.end()); std::swap(cards[0], cards[1]); // 자리 바꾸기 std::vector<int> blank(cards.size(), 0); // 0으로 채운 새 목록 show(cards); show(original); show(blank);}#include <stdio.h>#include <string.h> void show(const int *list, int n) { for (int i = 0; i < n; i++) printf(i > 0 ? " %d" : "%d", list[i]); printf("\n");} // 자리로 빼기: 뒤의 값들을 한 칸씩 당기고, 줄어든 개수를 돌려줘요int remove_at(int *list, int n, int at) { for (int i = at; i + 1 < n; i++) list[i] = list[i + 1]; return n - 1;} int main(void) { int n, x, cards[1000], original[1000], blank[1000]; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &cards[i]); scanf("%d", &x); int m = n; memcpy(original, cards, n * sizeof cards[0]); // 복사해 둬요 int at = -1; for (int i = 0; i < n && at < 0; i++) if (cards[i] == x) at = i; // 있나: 처음 나오는 자리 찾기 if (at >= 0) { printf("yes\n"); n = remove_at(cards, n, at); // 값으로 빼기 } else { printf("no\n"); } n = remove_at(cards, n, 0); // 자리로 빼기: 0번 for (int i = 0, j = n - 1; i < j; i++, j--) { // 뒤집기: 양 끝에서 맞바꿔요 int t = cards[i]; cards[i] = cards[j]; cards[j] = t; } int t = cards[0]; cards[0] = cards[1]; cards[1] = t; // 자리 바꾸기 for (int i = 0; i < n; i++) blank[i] = 0; // 0으로 채운 새 목록 show(cards, n); show(original, m); show(blank, n); return 0;}n = 콘솔.줄읽기().수로변환();cards = 콘솔.수들읽기();x = 콘솔.줄읽기().수로변환();original = cards.부분목록(0, cards.개수); // 복사해 둬요만약 (cards.있나(x)){ 콘솔.쓰기("yes"); cards.빼기(x); // 값으로 빼기: 처음 나오는 하나만}아니면{ 콘솔.쓰기("no");}cards.자리빼기(0); // 자리로 빼기: 0번cards.뒤집기();t = cards[0]; // 자리 바꾸기cards[0] = cards[1];cards[1] = t;blank = 새목록(cards.개수, 0); // 0으로 채운 새 목록콘솔.쓰기(cards);콘솔.쓰기(original);콘솔.쓰기(blank);5 30 10 40 10 50 10
yes 10 50 40 30 10 40 10 50 0 0 0
핵심
- 있는지 묻기는 참·거짓으로 답해요.
반복문으로 하나씩 비교하지 않아도 한 줄로 쓸 수 있어요(C는 반복문으로 찾아요). - 빼기는 두 가지예요.
자리로 빼기는 i번 칸을 없애고, 값으로 빼기는 그 값이 처음 나오는 칸 하나만 없애요.
어느 쪽이든 뒤의 값들이 한 칸씩 앞으로 당겨져요.
없는 값을 빼려 할 때 벌어지는 일은 언어마다 달라요. - 뒤집기는 새 목록을 만들지 않고 그 목록의 순서를 거꾸로 바꿔요.
- 자리 바꾸기: 두 칸의 값을 맞바꿀 때
a[0] = a[1]부터 쓰면a[0]의 원래 값이 사라져요.
임시 변수에 하나를 옮겨 두거나, 한 번에 맞바꾸는 문법을 써요. - 같은 값으로 채우기: 0이 n개 든 목록처럼, 크기와 처음 값만 주고 목록을 만들어요.
- 복사: 08 단원에서
b = a는 같은 목록에 이름을 하나 더 붙일 뿐이라고 했어요.
원래 목록을 남겨 두려면 고치기 전에 따로 복사해요.
Python·JavaScript·Java·C#·크레이콘의 이 복사는 한 겹만이에요.
목록 안에 목록이 든 격자(12 단원)는 복사해도 줄을 함께 쓰니까, 줄마다 따로 복사해요.
언어별로 쓰는 법
| Python | x in a.값으로 a.remove(x)(없으면 ValueError), 자리로 a.pop(i)나 del a[i].a.reverse().a[0], a[1] = a[1], a[0].[0] * n.복사는 a.copy() |
|---|---|
| JavaScript | a.includes(x).자리로 a.splice(i, 1).값으로 빼는 함수는 없어서 a.indexOf(x)로 자리를 찾아 splice.a.reverse().[a[0], a[1]] = [a[1], a[0]].new Array(n).fill(0).복사는 [...a] |
| TypeScript | JavaScript와 같아요 |
| Java | List<Integer>에서 a.contains(x).자리로 a.remove(i), 값으로 a.remove(Integer.valueOf(x))(없으면 false).Collections.reverse(a), Collections.swap(a, 0, 1).new ArrayList<>(Collections.nCopies(n, 0)).복사는 new ArrayList<>(a).배열 new int[n]은 처음부터 0으로 차 있어요 |
| C# | List<int>에서 a.Contains(x).값으로 a.Remove(x)(없으면 false), 자리로 a.RemoveAt(i).a.Reverse().(a[0], a[1]) = (a[1], a[0]).Enumerable.Repeat(0, n).ToList().복사는 new List<int>(a) |
| C++ | std::find(a.begin(), a.end(), x)가 a.end()가 아니면 있는 거예요.찾은 자리를 a.erase(it)로, i번은 a.erase(a.begin() + i)로 빼요.std::reverse(a.begin(), a.end()), std::swap(a[0], a[1]).std::vector<int> b(n, 0).b = a가 곧 복사예요 |
| C | 배열은 크기가 정해져 있고 이런 함수가 없어요. 반복문으로 찾고, 뺄 때는 뒤의 값들을 한 칸씩 당긴 뒤 개수를 직접 줄여요. 뒤집기는 양 끝에서 맞바꾸고, 맞바꾸기는 임시 변수 t로 해요.복사는 memcpy(b, a, n * sizeof a[0]) — b = a는 컴파일 오류예요 |
| Craykon | a.있나(x).값으로 a.빼기(x)(없으면 false), 자리로 a.자리빼기(i).a.뒤집기().맞바꾸기는 임시 변수로. 새목록(n, 0).복사는 a.부분목록(0, a.개수) |
자주 하는 실수
값 1을 빼려 했는데 1번 칸이 빠졌어요Java
List<Integer> a = new ArrayList<>(List.of(1, 2, 3));
a.remove(1);
System.out.println(a);→ [1, 3] — int를 넣으면 자리로 빼요. 1번 칸의 2가 빠졌어요
값으로 빼려면 a.remove(Integer.valueOf(1)) → [2, 3].[10, 20, 30]에 a.remove(10)을 쓰면 10번 칸을 찾다가 IndexOutOfBoundsException으로 멈춰요.
목록을 돌면서 그 목록에서 뺐어요Python · JavaScript · TypeScript · Java · C#
a = [1, 1, 2, 3]
for v in a:
if v == 1:
a.remove(v)
print(a)→ Python은 [1, 2, 3] — 뺀 자리로 다음 값이 당겨져서 두 번째 1을 건너뛰어요. JavaScript의 for...of도 같은 결과예요. Java는 ConcurrentModificationException, C#은 InvalidOperationException으로 멈춰요. 크레이콘의 각각만은 시작할 때의 목록을 따로 떠 놓고 돌아서, 1이 둘 다 빠진 2 3이 돼요
남길 값만 모아 새 목록을 만들거나 전용 함수를 써요: Python a = [v for v in a if v != 1], JavaScript a = a.filter(v => v !== 1), Java a.removeIf(v -> v == 1), C# a.RemoveAll(v => v == 1).
없는 값을 빼려 했더니 마지막 값이 빠졌어요JavaScript · TypeScript
const a = [1, 2, 3];
a.splice(a.indexOf(9), 1);
console.log(a);→ [ 1, 2 ] — 없으면 indexOf가 -1을 주고, splice(-1, 1)은 맨 뒤 칸을 빼요
먼저 있는지 확인해요: const i = a.indexOf(9); if (i !== -1) a.splice(i, 1);
뒤집기는 그 목록 자체를 바꾸는 명령이라, 결과를 받아 쓰면 안 되는 언어가 있어요.
Python에서
b = a.reverse()라고 쓰면 b는 None이에요.거꾸로 된 새 목록이 필요하면 Python은
a[::-1], JavaScript는 복사한 뒤 뒤집는 [...a].reverse()를 써요.그리고 C에서
int *b = a;는 복사가 아니라 같은 배열을 가리키는 이름이에요.b[0] = 9를 하면 a[0]도 9가 돼요.