データ · 13
リストの編集
含むか調べる、取り除く、逆にする、入れ替える、同じ値で埋める、コピー。
リストは作ったあとでも、値を取り除いたり順番を変えたりできます。
下の例はカードのリストをコピーしておき、ある数が入っているか調べて、あれば取り除き、先頭のカードを取り除き、逆順にし、先頭の2枚を入れ替えます。
そして編集したリスト、コピーしておいた元のリスト、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
ポイント
- 含むか調べると、真か偽で答えが返ります。
ループで一つずつ比べなくても1行で書けます(C はループで探します)。 - 取り除く方法は二つあります。
位置で取り除くと i 番の枠がなくなり、値で取り除くとその値が最初に出てくる枠一つだけがなくなります。
どちらも後ろの値が一つずつ前に詰まります。
ない値を取り除こうとしたときに起きることは言語によって違います。 - 逆にする操作は、新しいリストを作らず、そのリストの順番を反対にします。
- 入れ替え:二つの枠の値を入れ替えるとき、
a[0] = a[1]から書くとa[0]の元の値が消えます。
一時変数に片方を移しておくか、一度に入れ替える書き方を使います。 - 同じ値で埋める:0 が n 個入ったリストのように、大きさと最初の値だけを渡してリストを作ります。
- コピー:08 の単元で、
b = aは同じリストに名前をもう一つ付けるだけだと学びました。
元のリストを残したいときは、編集する前に別にコピーします。
Python・JavaScript・Java・C#・Craykon のこのコピーは1段だけです。
リストの中にリストが入った格子(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 で止まります。
ない値を取り除こうとしたら最後の値が消えた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 · 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 で止まります。Craykon の それぞれ だけは、始めるときのリストを写し取ってから回るので、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)。
逆にする操作はそのリスト自体を変える命令なので、結果を受け取って使ってはいけない言語があります。
Python で
b = a.reverse() と書くと b は None です。逆順の新しいリストがほしいときは、Python は
a[::-1]、JavaScript はコピーしてから逆にする [...a].reverse() を使います。また C の
int *b = a; はコピーではなく、同じ配列を指す名前です。b[0] = 9 とすると a[0] も 9 になります。