【问题标题】:How to sort a multidimensional array in order of appearance in Java?如何在Java中按出现顺序对多维数组进行排序?
【发布时间】:2015-09-09 22:03:10
【问题描述】:

如果标题不清楚,我举个例子:

我有一个按第一列排序的数组 - date,我需要按照列 name 中值的出现顺序再次对其进行排序

data[100][4]

date | name | text | type
-----+------+------+------
2222 | z    | wwww | 2
2221 | z    | qqqq | 1
2220 | c    | dasa | 2
2219 | b    | dsad | 1
2218 | z    | dfsa | 2
2217 | c    | dasd | 1

这是排序后的数组:

order[100][4]

date | name | text | type
-----+------+------+------
2222 | z    | wwww | 2
2221 | z    | qqqq | 1
2218 | z    | dfsa | 2
2220 | c    | dasa | 2
2217 | c    | dasd | 1
2219 | b    | dsad | 1

我想将这些数据合并到一个字符串中,并在列之间插入一些符号以便将来检索它,添加到ArrayList,然后按名称检索。我已将data[i][1] 添加到HashMap 以确定唯一值的数量,因此我可以知道循环周期的数量。还有名称值的顺序让我感到困惑,因为HashMap 不保持顺序。

有谁知道如何轻松地对其进行排序?

【问题讨论】:

  • 如果你想要排序,LinkedHashMap 会保留插入顺序。
  • 使用 Java 集合和比较器。

标签: java sorting multidimensional-array


【解决方案1】:

有一个对象代表一个带有日期、名称、文本和类型的数据条目,并让它实现Comparable 接口。 Comparable 接口有效地允许对对象执行不等式操作,并且是 Java API 用于对对象进行任何类型比较(用于排序)的接口。然后根据给定的字段对数据进行排序,在数据对象类中包含一个静态变量,表示要对哪个字段进行排序。

class Data implements Comparable<Data>
{
    int date;     // field 1
    String name;  // field 2
    String text;  // field 3
    int type;     // field 4

    static int sortField;
    static final int DATE = 1;
    static final int NAME = 2;
    static final int TEXT = 3;
    static final int TYPE = 4;

    // put constructor here

    //compareTo function for sorting
    public int compareTo(Data other)
    {
        if (sortField == DATE)
        {
            if (date < other.date)    return -1;
            if (date > other.date)    return 1;
            else                      return 0;
        }
        if (sortField == NAME)
        {
            return name.compareTo(other.name);
        }
        if (sortField == TEXT)
        {
            return text.compareTo(other.text);
        }
        else
        {
            if (type < other.type)    return -1;
            if (type > other.type)    return 1;
            else                      return 0;
        }
    }
}

然后你所要做的就是将对象放入ArrayList 并对其进行排序

ArrayList<Data> list = new ArrayList<Data>();

//put Data objects into list here

//to sort
Data.sortField = Data.DATE;   //sort by date - change as needed
Collections.sort(list);

【讨论】:

  • 但在这里它将是一维数组。问题说多维数组。
  • @RamanShrivastava List 中的 Data 对象包含最初使数组成为多维的多个数据点。
  • 知道了。但是如果我的其他类型的多维数组怎么办……或者我想在其中引入一些列。这将如何处理?
  • 你可以让课程动态化。代替每个字段的变量,您可以有一个 ArrayList,将每个字段以任意顺序存储在列表中,然后让 compareTo() 只返回 list.get(sortField).compareTo(other.list.get (排序字段))。 sortField 将是 ArrayList 中字段的索引。
  • 您的代码可以正常工作并对我的数据进行排序,但按字母顺序排列,我指定顺序必须是外观。喜欢:z, b, c, z, c, z, b 已排序 z, z, z, b, b, c, c
【解决方案2】:

我使用@Aderis 创建类的想法,但排序方法略有不同。此处发布了初始化数组的代码,但有人将其删除。反正我也用过。

String[][] myArr = { { "2222", "b", "dfsa", "2" },
                { "2221", "z", "wwww", "2" }, { "2220", "c", "qqqq", "1" },
                { "2219", "z", "dasa", "2" }, { "2218", "b", "dsad", "1" } };

HashMap<String,String> hashData = new HashMap<>();

for (int i = 0; i < myArr.length; i++) hashData.put(myArr[i][1],myArr[i][1]);
int unique_entries = hashData.size();

ArrayList<Data> list = new ArrayList<Data>();
ArrayList<Data> list_sorted = new ArrayList<Data>();

for (int i = 0; i < myArr.length; i++){
    Data temp = new Data(myArr[i][0],myArr[i][1],myArr[i][2],Integer.parseInt(myArr[i][3]));
    list.add(temp);
}

for (int k = 0; k < unique_entries; k++){
    boolean flag = true;
    ArrayList<Integer> elements = new ArrayList<>();
    int list_elements = list.size(); 
    for (int i = 0; i < list_elements; i++){
        if (flag){
            list_sorted.add(list.get(i));
            elements.add(i);
            flag = false;
            continue;
        }
        int list_sorted_elements = list_sorted.size(); 
        for (int j = 0; j < list_sorted_elements; j++){
            if (list_sorted.get(j).name.contains(list.get(i).name)){
                list_sorted.add(list.get(i));
                elements.add(i);
                break;
            }
        }
    }
    for (int i = 0; i < elements.size(); i++){ 
        int temp = elements.get(i);
        if (i != 0) temp = temp - i;
        list.remove(temp);
    }
}

如您所见,为了确定唯一元素的数量,我将它们添加到 HashMap 并检查其大小。我用我的数据对象填充ArrayList,并将排序的数据添加到另一个ArrayList,然后我从未排序的列表中删除这些数据并开始对其余数据进行排序。循环与唯一名称一样多。

我认为这不是最佳方式。但这是我知道的唯一方法。如果有人知道更快的方法,我会接受他们的帖子。

【讨论】:

    【解决方案3】:

    将此二维数组转换为 HashMap。对象部分将保存特定的数组元素。

    获取键集..将键集转换为列表..对列表进行排序..遍历列表并从映射中获取它们各自的数组元素。

    例如代码:

            String[][] myArr = new String[4][3];
            for (int i=0; i<myArr.length; i++) {
                myArr[i][0] = (i+1)+"1";
                myArr[i][1] = (i+1)+"2";
                myArr[i][2] = (i+1)+"3";
            }
    
            Map<String, Object> map = new HashMap<String, Object>();
            for (int i=myArr.length-1; i>=0; i--) {
                map.put(myArr[i][0], myArr[i]);
            }
    
            List<String> keyList = new ArrayList<String>(map.keySet());
    
            Collections.sort(keyList);
    
            String[][] myNewArray = new String[4][3];
            int a =0;
            for (String s : keyList) {
                myNewArray[a++] = ((String[])map.get(s));
            }
    

    我使用的是字符串,在你的情况下是日期。即使是其他内容,您也可以使用可比较或压缩器对该键列表进行排序。

    使用您的排序键作为 map 中的键。

    【讨论】:

    • 我猜你没有理解这个问题。数组中的数据已经按date排序,需要按出现顺序按name排序
    猜你喜欢
    • 1970-01-01
    • 2014-10-07
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多