在循环遍历列表时按索引删除列表项

3
public boolean isTwoPair() {
    boolean isTwoPair = false;
    Collections.sort(deck);
    List<Card> cards = new LinkedList<Card>(deck);
    System.out.println(cards);  
    for (int i = 0; i < cards.size()-1; i++) {
        for (int j = i + 1; j < cards.size()-1; j++) {
            if (deck.get(i).equals(deck.get(j))) {
                cards.remove(i);
                cards.remove(j);
                System.out.println(cards);
            }
        }

    }
    return isTwoPair;

}

我觉得我的问题在于cards.remove()。当我移除一张卡片时,下次再次移除卡片时会从修改后的列表中移除。有没有办法在它们具有相同索引号的情况下从列表中删除两个项?

如果我必须移除索引0,1,因为它们都是成对出现的,就像这样:

[Ace,Ace,Three,Four,Four]

代码会像这样删除它(删除索引0)。
[Ace,Three,Four,Four]

与其从第一个列表中删除索引1(Ace),不如从第二个列表中删除它,这样

[Ace,Four,Four]

它从第二个列表中删除了索引1,该索引对应的值是3。

这就是我期望的结果。

[Three,Four,Four]

在这个时候,我期望我的循环将选取并移除“Four”和“Four”。
编辑:
    public boolean isTwoPair() {
    boolean isTwoPair = false;
    Collections.sort(deck);
    List<Card> cards = new LinkedList<Card>(deck);
    System.out.println(cards);  
    for (int cardOne = 0; cardOne < cards.size(); cardOne++) {
        for (int cardTwo = cardOne + 1; cardTwo < cards.size(); cardTwo++) {
            if (deck.get(cardOne).equals(deck.get(cardTwo))) {
                cards.remove(cardOne);
                cards.remove(cardTwo-1);
                System.out.println(cards);
                for(int cardThree = 0; cardThree < cards.size(); cardThree++){
                    for(int cardFour = cardThree+1; cardFour < cards.size(); cardFour++){
                        if(cards.get(cardThree).equals(cards.get(cardFour))){
                            cards.remove(cardThree);
                            cards.remove(cardFour-1);
                            System.out.println(cards);
                            isTwoPair = true;
                        }
                    }
                }
            }
        }

    }
    return isTwoPair;

}

我现在正在使用的是这个,如果不必要的话,我并不想新建一个变量,因此我决定不删除 Object。


不要删除Aces,只需将它们形成一对的事实保存在某个地方。 - Michał Rybak
1
另一个选择是用 null 替换项目,并忽略掉 null 项。 - Jason C
我实际上尝试了将数组索引设置为null,但立即出现了错误,我该如何忽略null? - gallly
@droidbehavior 你只需要处理那些不为空的事物... if (deck.get(cardOne) != null) { ... } - Jason C
4个回答

3

如果你知道j始终大于i(因为for循环的缘故),如果你先删除索引为i的元素,那么你可以接着删除索引为j - 1的元素,并得到预期的结果。

cards.remove(i);
cards.remove(j-1);

1
你确定要从 i = 0 循环到 < cards.size()-1 吗?因为这样会漏掉一张牌,试试 i < cards.size() - Christian Tapia

2
使用 List.remove(Object) 代替 List.remove(int)。这样就不再依赖于列表的顺序了。
public boolean isTwoPair() {
    boolean isTwoPair = false;
    Collections.sort(deck);
    List<Card> cards = new LinkedList<Card>(deck);
    for (int i = 0; i < cards.size()-1; i++) {
        for (int j = i + 1; j < cards.size()-1; j++) {
            cardI = deck.get(i);
            cardJ = deck.get(j);
            if (cardI.equals(cardJ)) {
                cards.remove(cardI);
                cards.remove(cardJ);
                isTwoPair = true;
            }
        }

    }
    return isTwoPair;

}

谢谢,这个方法有效,我不知道有一个选项可以移除对象。 - gallly

1
问题在于,当你从列表中删除一个对象时,你没有考虑到删除后大小不同以及元素的索引在删除后发生变化的情况。
假设你想要删除索引为0和1的元素。
initially => [Ace,Ace,Three,Four,Four]
               0   1    2     3    4

移除 [0]
after removing [0] => [Ace,Three,Four,Four]
                        0    1     2    3

删除 [1]

after removing [1] => [Ace,Four,Four]
                        0   1     2   

因此,您不能使用索引进行删除,而是使用List.remove(Object)

1
cards.remove(i);
cards.remove(j);

LinkedList 中删除元素后,它会将随后的元素向左移动(从它们的索引中减去一个)。如果 j > i,可以使用 j-1 替代 j。或者,使用 cards.remove(Card)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接