如何删除数组中的项目并保持顺序不变?

How to delete an item in the array and keeping the order the same?

提问人: 提问时间:10/8/2021 更新时间:10/8/2021 访问量:480

问:

我正在做这个项目,允许我在数组中添加和删除元素。当我删除数组中的元素时,该空间中会有一个零,代码应该在删除的值之后移动值以取代它。例如:在数组 {1, 2, 3, 4, 5} 中。我选择删除 3.我的输出应该是 {1, 2, 4, 5}。相反,我的输出是 {1, 2, 5, 4}。有人可以帮我弄清楚为什么它会这样做吗?以及如何纠正它?

import java.util.Scanner;
import java.util.Arrays;

public class IntBag2 {
    private static final int INITIAL_SIZE = 20;
    private static int[] bag;
    private int capacity;

    public IntBag2() {
        bag = new int[INITIAL_SIZE];
    }

    public IntBag2(int capacity) {
        bag = new int[capacity];
    }

    public boolean add(int item) {
        if (capacity == bag.length)
            return false;

        bag[capacity++] = item;

        return true;
    }

    public boolean delete(int item) {
        for (int i = 0; i < capacity; i++) {
            if (bag[i] == item) {
                bag[i] = bag[--capacity];
                return true;
            }
        }

        return false;
    }

    @Override
    public String toString() {
        String result = "Bag: ";
        for (int i = 0; i < capacity; i++)
            result += bag[i] + " ";
        return result;
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        IntBag2 intBag = new IntBag2();
        boolean done = false;

        while (!done) {
            System.out.println("1. Add an Item to the Array");
            System.out.println("2. Delete an item in the Array");
            System.out.println("3. toString");
            switch (input.nextInt()) {
            case 1:
                System.out.println("Add an Item to the Array");
                System.out.println(intBag.add(input.nextInt()));
                break;
            case 2:
                System.out.println("Delete Item of Array");
                System.out.println(intBag.delete(input.nextInt()));
                break;
            case 3:
                System.out.println("toString");
                System.out.println(intBag.toString());
                break;
            }
        }
        input.close();
    }

}
Java 数组 eclipse java.util.scanner

评论

0赞 greg-449 10/8/2021
你可能想看看的来源 - 特别是方法。java.util.ArrayListremove()
0赞 10/8/2021
我不被允许使用数组列表,该项目是关于部分填充的数组。
0赞 greg-449 10/8/2021
是的,但您可以阅读源代码以了解事情是如何完成的。

答:

0赞 João Dias 10/8/2021 #1

使用该行,您基本上可以获取数组中的最后一项,并将其放置在已删除的项的位置。bag[i] = bag[--capacity];

假设您使用的是(而不是 ),我们不能将数组的索引指定为 。我们能做的最好的事情就是分配它或创建一个新数组。int[]Integer[]null-1

我决定从头开始创建一个新数组。以下方法就可以了。

public class IntBag2 {
    private static final int INITIAL_SIZE = 20;
    private static int[] bag;
    private int capacity;

    public IntBag2() {
        bag = new int[INITIAL_SIZE];
    }

    public IntBag2(int capacity) {
        bag = new int[capacity];
    }

    public boolean add(int item) {
        if (capacity == bag.length)
            return false;

        bag[capacity++] = item;

        return true;
    }

    public boolean delete(int item) {
        int[] newBag = new int[capacity];
        int newCapacity = capacity;
        boolean deleted = false;
        for (int i = 0, j = 0; i < capacity; i++) {
            if (bag[i] == item && !deleted) {
                deleted = true;
                newCapacity = capacity - 1;
            } else {
                newBag[j++] = bag[i];
            }
        }

        bag = newBag;
        capacity = newCapacity;
        return deleted;
    }

    @Override
    public String toString() {
        String result = "Bag: ";
        for (int i = 0; i < capacity; i++)
            result += bag[i] + " ";
        return result;
    }
}

评论

0赞 10/8/2021
那么我该如何更改它以获取数组中的下一项并将其放置在已删除项的位置呢?
0赞 João Dias 10/8/2021
你能从 Apache Commons 使用吗?ArrayUtils
0赞 João Dias 10/8/2021
我在我的答案中添加了一个可能的解决方案。如果它不适合或用例,请告诉我。
0赞 10/8/2021
顺序是固定的,但输出现在是 {1, 2, 4, 5, -1} 如果我从数组 {1, 2, 3, 4, 5} 中删除 3;
0赞 10/8/2021
我将如何使用 ArrayUtils?
0赞 Nowhere Man 10/8/2021 #2

一个更简单的实现是可能的,允许“删除”数组中给定条目相等的所有条目,并有效地将剩余的条目移到前面:deleteitem

public boolean delete(int item) {
    System.out.println("deleting " + item); // for debug purposes
    int oldCapacity = capacity;
    for (int i = 0, j = 0; i < oldCapacity; i++) {
        if (bag[i] != item) {
            bag[j++] = bag[i];
        } else {
            capacity--;
        }
    }
    System.out.println("new capacity = " + capacity); // for debug

    // or use Arrays.fill(bag, capacity, oldCapacity, -1); instead of the loop
    for (int i = capacity; i < oldCapacity; i++) {
        bag[i] = -1; // mark free entries with -1 in the tail
    }

    return oldCapacity == capacity;
}

此外,如果在循环中使用多个串联,则应使用方法,或者为了简洁起见,可以使用以下实用程序方法实现:toStringStringBuilderprintArrays

public void print() {
    System.out.println(Arrays.toString(Arrays.copyOf(bag, capacity)));
}

测试:

IntBag ibag = new IntBag(10);
ibag.add(1);
ibag.add(3);
ibag.add(3);
ibag.add(2);
ibag.add(1);
ibag.print();
ibag.delete(2);
ibag.print();
ibag.delete(1);
ibag.print();

输出:

[1, 3, 3, 2, 1]
deleting 2
new capacity = 4
[1, 3, 3, 1]
deleting 1
new capacity = 2
[3, 3]

更新

仅“删除”第一个条目而不创建新数组,可以按如下方式实现:

  • 跳过所有元素,直到检测到或达到结束itembag
  • 如果找到,将剩余元素移位 1,将 -1 写入最后一个元素,返回itemtrue
  • 否则返回false
public boolean deleteFirst(int item) {
    System.out.println("deleting first " + item);
    int id = 0;
    while (id < capacity && bag[id] != item) id++;
    if (id < capacity && bag[id] == item) {
        while (++id < capacity) {
            bag[id - 1] = bag[id];
        }
        bag[--capacity] = -1;
        return true;
    }
    return false;
}

测试:

IntBag ibag = new IntBag(10);
ibag.add(1); ibag.add(3); ibag.add(1); ibag.add(2); ibag.add(1);
ibag.print();
ibag.deleteFirst(1); ibag.print();
ibag.deleteFirst(1); ibag.print();
ibag.deleteFirst(1); ibag.print();

输出:

[1, 3, 1, 2, 1]
deleting first 1
[3, 1, 2, 1]
deleting first 1
[3, 2, 1]
deleting first 1
[3, 2]

评论

0赞 10/8/2021
我需要删除方法仅在项目第一次出现时删除它,而不是每次都删除它。我之所以要求使用这种方法,是因为我需要实现另一种方法来删除您提供给我的所有内容。现在我需要该方法在项目第一次出现时将其删除。
0赞 Nowhere Man 10/8/2021
@EzequielSoler,您可以检查更新