首页 > 解决方案 > 向 2d Arraylist 添加两次的术语

问题描述

0

上下文:我正在尝试随机打乱 2D 数组列表。

例如,如果我有下面的二维数组列表(可以在任一方向上一样长),我想根据输入索引将所有相似的值一起移动(例如,将所有 b 移动到它们各自数组的开头)。

[[a,b,c]                               [[b,c,a]

,[a,b,c]                ==>            ,[b,c,a]

,[a,b,c]]                              ,[b,c,a]]

我正在使用具有两个数据结构的方法。将数据添加到新数据结构中并从旧数据结构中删除,直到所有垂直组都被洗牌。

我的第一次尝试改变了数组的顺序,而不是它们的内容。

我决定先尝试将一组数据添加到新的数据结构中,但它会将术语添加到所有数组中,尽管它甚至没有多次运行代码行。

例如,如果上面的每个 'b' 的值都是 1,2,3 而不是输出 [1][2][3],它会输出 [1,2,3][1,2,3][1, 2,3]。我已经测试了每一行代码的输出,它会按计划进行,直到terms2shuffled.get(k).add(intermediateTerms.get(k).get(j));

我的代码:

ArrayList<ArrayList<String>> intermediateTerms = new ArrayList<>();
           terms2shuffled = new ArrayList<>();
           
           ArrayList<String> temp = new ArrayList();
           for(int i = 0;i<columnNumber;i++){
               terms2shuffled.add(temp);
           }
           
           intermediateTerms=terms2;            
           
           int length = intermediateTerms.get(0).size();
               int j = random.nextInt(length);
               for(int k = 0; k<numColumns;k++){
                   System.out.println(intermediateTerms.get(k).get(j));
                   terms2shuffled.get(k).add(intermediateTerms.get(k).get(j));
                   System.out.println(terms2shuffled);

                   //intermediateTerms.remove(j);
               

(其中 wordsNumber == NO. of rows NumColumns == NO. of columns)

谢谢你的帮助

标签: javaarraysarraylist

解决方案


以下代码行:

ArrayList<String> temp = new ArrayList();
for(int i = 0;i<columnNumber;i++){
    terms2shuffled.add(temp);
}

...为每一行添加相同的ArrayList实例,这意味着以下行:

terms2shuffled.get(k).add(intermediateTerms.get(k).get(j));

...将修改该单个实例(因为terms2shuffled.get(k)将始终给您temp),这应该可以解释原因:

它将术语添加到所有数组

相反,您可以尝试:

for(int i = 0; i < columnNumber; i++) {
    terms2shuffled.add(new ArrayList<>());
}

为了List每行都有一个单独的实例。


在以下代码中:

intermediateTerms=terms2;

...我假设这terms2是原始的二维列表,所以我应该在这里注意,通过修改intermediateTerms后面的内容,您实际上也在修改terms2列表,因为它们都指向同一个实例。如果您不想修改原始列表,则应创建它的深层副本,然后将深层副本分配给intermediateTerms. 由于terms2是二维的,一个简单的terms2.clone();是不够的。


以下for-loop 声明:

for (int k = 0; k < numColumns; k++)

用作k列的索引,但随后在循环体中k用于获取二维中的List。由于您的二维List是正方形的,因此根本不重要。我只是注意到这一点。据我所知,这可能不会阻止有人将行解释为列,将列解释为行,所以我在这里假设最简单的情况,这就是我注意到这一点的原因。


如果我有下面的二维数组列表(可以在任一方向上一样长),我想根据输入索引将所有相似的值一起移动(例如,将所有 b 移动到它们各自数组的开头)。

在您给出的代码中,您似乎只执行一个操作(即在每一行中移动一列,而不是在每一行中移动多列)。相反,您可能希望多次重复该过程,如下所示(在伪代码中):

将 terms2 中的所有值深度复制到结果列表中。
对于每一列(名为“c”)重复:
    生成一个随机列(名为“r”)以更改其在每一行中的位置。
    对于每一行(在结果列表中)重复:
        将行中的“c”列交换为“r”。

但这似乎还不够,因为您只会以每行为基础进行洗牌,这意味着例如第二行中的元素将始终保留在第二行中。即使在那之后你打乱了行,那么仍然有些元素永远不会离开他们的行。相反,您可能希望在每个单元格的基础上进行洗牌(这样的示例逻辑和代码将在本文后面紧随其后)。


我正在尝试随机打乱 2D 数组列表。

将二维中的所有值随机化List(以每个单元为基础)的一种方法是:

  1. 将二维折叠为List一维。
  2. 单维度洗牌。
  3. 从打乱的单一维度重新创建维度List

例如:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class ListUtils {
    
    public static <T> void collapseFrom2D(final List<? extends List<T>> inputList2D,
                                          final List<T> outputList1D) {
        inputList2D.forEach(outputList1D::addAll);
    }
    
    public static <T> void setAll(final Iterator<T> inputIter,
                                  final ListIterator<T> outputIter,
                                  final long limit) {
        for (long i = 0; outputIter.hasNext() && inputIter.hasNext() && i < limit; ++i) {
            outputIter.next();
            outputIter.set(inputIter.next());
        }
    }
    
    public static <T> void setAll(final Iterator<T> inputIter,
                                  final ListIterator<T> outputIter) {
        setAll(inputIter, outputIter, Integer.MAX_VALUE);
    }
    
    public static <T> void expandTo2D(final Iterator<T> inputValuesIter,
                                      final List<? extends List<T>> outputList2D) {
        final Iterator<? extends List<T>> outputIter = outputList2D.iterator();
        while (outputIter.hasNext())
            setAll(inputValuesIter, outputIter.next().listIterator());
    }
    
    public static <T> void expandTo2D(final List<T> inputList1D,
                                      final List<? extends List<T>> outputList2D) {
        expandTo2D(inputList1D.iterator(), outputList2D);
    }
    
    public static <T> void shuffle2D(final List<? extends List<T>> list) {
        final ArrayList<T> singleDimension = new ArrayList<>();
        collapseFrom2D(list, singleDimension);
        Collections.shuffle(singleDimension);
        expandTo2D(singleDimension, list);
    }
    
    public static void main(final String[] args) {
        final ArrayList<List<Integer>> list = new ArrayList<>();
        list.add(Arrays.asList(1, 2));
        list.add(Arrays.asList(3, 4, 5, 6));
        list.add(Collections.emptyList());
        list.add(Arrays.asList(7, 8, 9));
        System.out.println("Before: " + list);
        shuffle2D(list);
        System.out.println("After: " + list);
    }
}

据我了解,这可以概括为 -n维列表或数组。

上面给出的示例代码不必在 square 上运行List。它也适用于非矩形Lists。


推荐阅读