{ }codelper
リストからの削除P0058

同じ値をすべて取り除く

一行目に個数 n、二行目に整数 n 個、三行目に整数 x が与えられる。
リストから x と等しい値をすべて取り除け。
一行目に残った個数を、二行目に残った数を元の順に空白一つ区切りで出力せよ。
何も残らなければ一行目に 0 を書き、二行目は空行にする。
x がリストになければリストはそのままである。

入力
1 ≤ n ≤ 10,000、すべての数と x は -1,000 以上 1,000 以下の整数
出力
二行:残った個数、残った数(なければ空行)
例 1 · stdin
8
2 2 1 2 2 2 3 2
2
stdout
2
1 3
例 2 · stdin
3
4 4 4
4
stdout
0

main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

いちばん多い落とし穴は前から回りながら消すことです。
一つ消すと後ろが一つずつ詰まるのに番号はそのまま一つ進むので、並んだ "2 2" の二つ目の 2 を飛ばします。
Python の for v in a: a.remove(v) も同じ理由で飛ばします。
直し方は二つ:残すものだけ新しいリストに集める(Python [v for v in a if v != x]、JavaScript・TypeScript a.filter(v => v !== x))か、後ろから消すか。
一度に全部消す道具:Java list.removeIf(v -> v == x)、C# list.RemoveAll(v => v == x)、C++20 std::erase(a, x)(それ以前は erase-remove イディオム)、C は残すものを前へ詰めて書く番号ひとつ。
落とし穴はあと二つ:JavaScript の a.splice(a.indexOf(x), 1) は一つしか消さず、x がないと indexOf が -1 なので最後の要素を消します。
Java の List<Integer> の remove(x) に int を渡すと値ではなく x 番目の位置を消します(値なら remove(Integer.valueOf(x)))。
Craykon は後ろから a.位置で取り除く(i) で消しました(a.取り除く(x) は一つだけ消します)。

Pythonmain.py · 6 行
n = int(input())a = list(map(int, input().split()))x = int(input())rest = [v for v in a if v != x]print(len(rest))print(*rest)
JavaScriptmain.js · 5 行
const [n, ...rest] = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const a = rest.slice(0, n);const x = rest[n];const left = a.filter((v) => v !== x);console.log(left.length + "\n" + left.join(" "));
TypeScriptmain.ts · 6 行
import { readFileSync } from "node:fs";const [n, ...rest]: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const a: number[] = rest.slice(0, n);const x: number = rest[n];const left: number[] = a.filter((v) => v !== x);console.log(left.length + "\n" + left.join(" "));
JavaMain.java · 19 行
import java.util.ArrayList;import java.util.List;import java.util.Scanner;import java.util.StringJoiner; public class Main {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        int n = sc.nextInt();        List<Integer> a = new ArrayList<>();        for (int i = 0; i < n; i++) a.add(sc.nextInt());        int x = sc.nextInt();        a.removeIf(v -> v == x);        StringJoiner out = new StringJoiner(" ");        for (int v : a) out.add(String.valueOf(v));        System.out.println(a.size());        System.out.println(out);    }}
C#Main.cs · 16 行
using System;using System.Collections.Generic;using System.Linq; class Program{    static void Main()    {        Console.ReadLine();        List<int> a = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList();        int x = int.Parse(Console.ReadLine());        a.RemoveAll(v => v == x);        Console.WriteLine(a.Count);        Console.WriteLine(string.Join(" ", a));    }}
C++main.cpp · 14 行
#include <iostream>#include <vector> int main() {    int n, x;    std::cin >> n;    std::vector<int> a(n);    for (int& v : a) std::cin >> v;    std::cin >> x;    std::erase(a, x);  // C++20. 그 전에는 a.erase(std::remove(a.begin(), a.end(), x), a.end());    std::cout << a.size() << "\n";    for (size_t i = 0; i < a.size(); i++) std::cout << (i ? " " : "") << a[i];    std::cout << "\n";}
Cmain.c · 16 行
#include <stdio.h> int main(void) {    static int a[10000];    int n, x, m = 0;    scanf("%d", &n);    for (int i = 0; i < n; i++) scanf("%d", &a[i]);    scanf("%d", &x);    /* 남길 것만 앞으로 당겨 쓴다: m은 다음에 쓸 자리 */    for (int i = 0; i < n; i++)        if (a[i] != x) a[m++] = a[i];    printf("%d\n", m);    for (int i = 0; i < m; i++) printf(i ? " %d" : "%d", a[i]);    putchar('\n');    return 0;}
Craykonmain.cray · 13 行
n = コンソール.行読み().数に();a = コンソール.数読み();x = コンソール.行読み().数に();// 뒤에서부터 지우면 지운 뒤 당겨지는 칸을 건너뛰지 않는다繰り返す (i = a.個数 - 1; i >= 0; i--){    もし (a[i] == x)    {        a.位置で取り除く(i);    }}コンソール.書く(a.個数);コンソール.書く(a);