java java中如何对多个数组进行排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12164795/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 07:51:48  来源:igfitidea点击:

How to sort multiple arrays in java

javaarrayssorting

提问by 074Geodude

I'm trying to sort three arrays by lexicographical order. The arrays are related to each other by a common array. It's easier to explain if I demonstrate:

我正在尝试按字典顺序对三个数组进行排序。这些数组通过一个公共数组相互关联。如果我演示一下就更容易解释了:

int[] record = new int[4];
String [] colors = {"blue", "yellow", "red", "black"};
String [] clothes = {"shoes", "pants", "boots", "coat"};

When printed on the console, I would like them to be put in three columns similar to below:

在控制台上打印时,我希望将它们放在类似于下面的三列中:

Unsorted:

未分类:

Record  Color   Clothes
0       blue    shoes
1       yellow  pants
2       red     boots
3       black   coat

Sorted by Color:

按颜色排序:

Record  Color   Clothes
3       black   coat
0       blue    shoes
2       red     boots
1       yellow  pants

Sorted by Clothes:

按衣服分类:

Record  Color   Clothes
2       red     boots
3       black   coat
1       yellow  pants
0       blue    shoes

I found a previous answer similar to my scenario, but it compared integers instead of strings, and I'm having trouble using the compareTo()method and Arrays.sort()to arrive at my desired output.

我找到了与我的场景类似的先前答案,但它比较的是整数而不是字符串,并且我在使用该compareTo()方法并Arrays.sort()获得所需的输出时遇到了问题。

Any help would be appreciated!

任何帮助,将不胜感激!

回答by bcorso

In some cases it doesn't make much sense to create a new class just to do sorting.

在某些情况下,创建一个新类只是为了进行排序并没有多大意义。

Here, is a function that can be used to sort an any number of arbitrarily typed lists (List<?>) based on a key list (List<T implements Comparable>). Ideone Example here.

这是一个函数,可用于List<?>根据键列表 ( List<T implements Comparable>)对任意数量的任意类型列表 ( )进行排序。 此处为 Ideone 示例



Usage

用法

Here is an example of how you can use the function to sort multiple lists of arbitrary types:

下面是一个示例,说明如何使用该函数对多个任意类型的列表进行排序:

List<Integer> ids = Arrays.asList(0, 1, 2, 3);
List<String> colors = Arrays.asList("blue", "yellow", "red", "black");
List<String> clothes = Arrays.asList("shoes", "pants", "boots", "coat");

// Sort By ID
concurrentSort(ids, ids, colors, clothes);

// Sort By Color
concurrentSort(colors, ids, colors, clothes);

// Sort By Clothes
concurrentSort(clothes, ids, colors, clothes);

Output:

输出:

// Sorted By ID:
ID:      [0, 1, 2, 3]
Colors:  [blue, yellow, red, black]
Clothes: [shoes, pants, boots, coat]

// Sorted By Color:
ID:      [3, 0, 2, 1]
Colors:  [black, blue, red, yellow]
Clothes: [coat, shoes, boots, pants]

// Sorted By Clothes:
ID:      [2, 3, 1, 0]
Colors:  [red, black, yellow, blue]
Clothes: [boots, coat, pants, shoes]


Code

代码

An Ideone Example can be found herewhich includes validation of parameters and a test case.

可以在此处找到 Ideone 示例其中包括参数验证和测试用例。

public static <T extends Comparable<T>> void concurrentSort(
                                        final List<T> key, List<?>... lists){
    // Create a List of indices
    List<Integer> indices = new ArrayList<Integer>();
    for(int i = 0; i < key.size(); i++)
        indices.add(i);

    // Sort the indices list based on the key
    Collections.sort(indices, new Comparator<Integer>(){
        @Override public int compare(Integer i, Integer j) {
            return key.get(i).compareTo(key.get(j));
        }
    });

    // Create a mapping that allows sorting of the List by N swaps.
    // Only swaps can be used since we do not know the type of the lists
    Map<Integer,Integer> swapMap = new HashMap<Integer, Integer>(indices.size());
    List<Integer> swapFrom = new ArrayList<Integer>(indices.size()),
                  swapTo   = new ArrayList<Integer>(indices.size());
    for(int i = 0; i < key.size(); i++){
        int k = indices.get(i);
        while(i != k && swapMap.containsKey(k))
            k = swapMap.get(k);

        swapFrom.add(i);
        swapTo.add(k);
        swapMap.put(i, k);
    }

    // use the swap order to sort each list by swapping elements
    for(List<?> list : lists)
        for(int i = 0; i < list.size(); i++)
            Collections.swap(list, swapFrom.get(i), swapTo.get(i));
}


NOTE:The running time is O(mlog(m) + mN)where mis the length of the list and Nis the number of lists. Usually m >> Nso the running time is not more significant than sorting only the key O(mlog(m)).

注:在运行时间O(mlog(m) + mN),其中m是列表的长度,N是列表的数目。通常m >> N所以运行时间并不比只排序键更重要O(mlog(m))

回答by Keppil

Since Record, Colorand Clothesseem to belong together, I would suggest moving them together in a custom Object, eg

由于Record,Color并且Clothes似乎属于一起,我建议将它们一起移动到自定义对象中,例如

public class ClothesItem {
    int record;
    String color;
    String clothes;
}  

Then you can make different Comparators to do the different variants of sorting.

然后你可以制作不同的Comparators来做不同的排序变体。

If you need to preserve your current structure with multiple arrays, @Jherico has a sorting solution herethat gets an array of the sorted indexes, which should make it trivial to get to your wanted result.

如果您需要使用多个数组保留当前结构,@Jherico 在这里有一个排序解决方案,可以获取排序索引的数组,这应该可以轻松获得您想要的结果。

回答by 074Geodude

Alright, here's what it looks like in final form.

好的,这是最终形式的样子。

// ColorClothes.java

import java.util.*;


public class ColorClothes
{
public int record;
public String color;
public String clothes;

public static void main(String[] args)
{
    Initialize();
}

public ColorClothes(int record, String color, String clothes)
{
    this.record = record;
    this.color = color;
    this.clothes = clothes;
}

public static void Initialize()
{
    List<ColorClothes> list = new ArrayList();
    list = CreateList();

    Sort(list, "Unsorted", 1);
    Sort(list, "\nSortedByColor", 2);
    Sort(list, "\nSortedByClothes", 3);
    Sort(list, "\nSortedByRecord", 4);
}


public static List<ColorClothes> CreateList()
{
    List<ColorClothes> list = new ArrayList();
    list.add(new ColorClothes(1, "blue  ", "shoes"));
    list.add(new ColorClothes(0, "yellow", "pants"));
    list.add(new ColorClothes(3, "red   ", "boots"));
    list.add(new ColorClothes(2, "black ", "coat"));

    return list;
}

public static void Print(List<ColorClothes> list)
{
    for (ColorClothes item : list)
    {
        System.out.println(item.record + "    " + item.color + "   " + item.clothes);
    }
}

public static void Sort(List<ColorClothes> list, String string, int choice)
{
    System.out.println(string + "\n");

    switch (choice)
    {
    case 1:
        break;
    case 2:
        Collections.sort(list, new ColorComparator());
        break;
    case 3:
        Collections.sort(list, new ClothesComparator());
        break;
    case 4:
        Collections.sort(list, new RecordComparator());
        break;
    }

    Print(list);
}

} // End class.


// ColorComparator.java

import java.util.Comparator;

 class ColorComparator implements Comparator
 {
public int compare(Object str1, Object str2)
{
    String str1Color = ((ColorClothes)str1).color;
    String str2Color = ((ColorClothes)str2).color;

    return str1Color.compareTo(str2Color);

}
}// End class.


// ClothesComparator.java

import java.util.Comparator;


class ClothesComparator implements Comparator
{
public int compare(Object str1, Object str2)
{
    String str1Clothes = ((ColorClothes)str1).clothes;
    String str2Clothes = ((ColorClothes)str2).clothes;

    return str1Clothes.compareTo(str2Clothes);

}
} // End class.


// RecordComparator.java

import java.util.Comparator;


public class RecordComparator implements Comparator 
{
public int compare(Object rec1, Object rec2)
{
    int rec1Rec = ((ColorClothes)rec1).record;
    int rec2Rec = ((ColorClothes)rec2).record;

    if(rec1Rec > rec2Rec)
    {
        return 1;
    }
    else if(rec1Rec < rec2Rec)
    {
        return -1;
    }
    else
    {
        return 0;
    }
}
}// End class.

Console Output

控制台输出

Unsorted

1    blue     shoes
0    yellow   pants
3    red      boots
2    black    coat

SortedByColor

2    black    coat
1    blue     shoes
3    red      boots
0    yellow   pants

SortedByClothes

3    red      boots
2    black    coat
0    yellow   pants
1    blue     shoes

SortedByRecord

0    yellow   pants
1    blue     shoes
2    black    coat
3    red      boots

回答by count0

Sort the arrays in-directly. Index all your arrays and sort only the index-array of the desired array. Take a look at the solution in this SO post. This will keep your arrays consistent. I'm not sure if it's easy to extrapolate this to sorting N-arrays in sync though, but it should give you an idea of how to approach the problem in case you want to stick with having your data distributed in multiple arrays. As several people already pointed out, grouping the data in a single object is a good approach.

直接对数组进行排序。索引所有数组并仅对所需数组的索引数组进行排序。看看这个SO post中的解决方案。这将使您的阵列保持一致。不过,我不确定将其推断为同步排序 N 数组是否容易,但是如果您想坚持将数据分布在多个数组中,它应该让您了解如何解决这个问题。正如一些人已经指出的那样,将数据分组到一个对象中是一种很好的方法。

回答by Bharat Sinha

I am not sure about sorting multiple arrays at once; looking at the use case used by you this looks like a contender where all 3 attributes can be combined into an object and then the array of objects can be sorted in multiple ways.

我不确定一次对多个数组进行排序;看看您使用的用例,这看起来像是一个竞争者,其中所有 3 个属性都可以组合成一个对象,然后可以以多种方式对对象数组进行排序。

Are you sure that you need to have 3 arrays?

你确定你需要有 3 个数组吗?

Does an array of ColoredClothwould work for you like:

是否ColoredCloth对您有用的数组如下:

class ColoredCloth implements Comparable<ColoredCloth>{
    int id;
    String color;
    String cloth;
}

and define a couple of Comparatorsto sort by colorand cloth.

并定义几个Comparators以按color和排序cloth

回答by intrepidis

Here is how I sort two or more string arrays of the same length, so that the first array is in order and the other arrays match that order:

这是我对两个或多个相同长度的字符串数组进行排序的方法,以便第一个数组按顺序排列,其他数组与该顺序匹配:

public static void order(String[]... arrays)
{
    //Note: There aren't any checks that the arrays
    // are the same length, or even that there are
    // any arrays! So exceptions can be expected...
    final String[] first = arrays[0];

    // Create an array of indices, initially in order.
    Integer[] indices = ascendingIntegerArray(first.length);

    // Sort the indices in order of the first array's items.
    Arrays.sort(indices, new Comparator<Integer>()
        {
            public int compare(Integer i1, Integer i2)
            {
                return
                    first[i1].compareToIgnoreCase(
                    first[i2]);
            }
        });

    // Sort the input arrays in the order
    // specified by the indices array.
    for (int i = 0; i < indices.length; i++)
    {
        int thisIndex = indices[i];

        for (String[] arr : arrays)
        {
            swap(arr, i, thisIndex);
        }

        // Find the index which references the switched
        // position and update it with the new index.
        for (int j = i+1; j < indices.length; j++)
        {
            if (indices[j] == i)
            {
                indices[j] = thisIndex;
                break;
            }
        }
    }
    // Note: The indices array is now trashed.
    // The first array is now in order and all other
    // arrays match that order.
}

public static Integer[] ascendingIntegerArray(int length)
{
    Integer[] array = new Integer[length];
    for (int i = 0; i < array.length; i++)
    {
        array[i] = i;
    }
    return array;
}

public static <T> void swap(T[] array, int i1, int i2)
{
    T temp = array[i1];
    array[i1] = array[i2];
    array[i2] = temp;
}

If you want to do this with arrays of other types then you will need to refactor this somewhat. Alternatively, for an integer array to be sorted along with string arrays you could convert the integers to strings.

如果你想用其他类型的数组来做这件事,那么你需要稍微重构一下。或者,对于要与字符串数组一起排序的整数数组,您可以将整数转换为字符串。

回答by brthornbury

Put the data into a custom class like @SiB:

将数据放入像@SiB 这样的自定义类中:

class ColoredClothes {
    int id;
    String color;
    String cloth;
}

Then, put each instance of this class into a TreeMap with the color as the key (or cloth name depending what you want to sort by):

然后,将此类的每个实例放入一个以颜色为键的 TreeMap(或布料名称,取决于您要排序的内容):

TreeMap<String,ColoredClothes> sortedCloth= new TreeMap<String,ColoredClothes>();
//loop through arrays and put new ColoredClothes into Map

Then get the sorted values like so:

然后像这样得到排序的值:

Collection<ColoredClothes> values = sortedCloth.values();

You can iterate through these in order by using values.iterator()

您可以使用 values.iterator() 按顺序遍历这些

回答by jazzgil

Liked @bcorso's idea of creating swapping lists to sort any other List. Here's a bit more optimized version, that uses only 2 arrays instead of a Map and 3 ListArrays, and only swaps indexes that need swapping:

喜欢@bcorso 创建交换列表以对任何其他列表进行排序的想法。这是一个更优化的版本,它只使用 2 个数组而不是 Map 和 3 个 ListArrays,并且只交换需要交换的索引:

public static <T extends Comparable<T>> void syncedSort(final List<T> key, List<?>... lists) {
    // Create an array of indices
    Integer[] indices = new Integer[key.size()];
    for (int i = 0; i < indices.length; i++)
        indices[i] = i;

    // Sort the indices array based on the key
    Arrays.sort(indices, new Comparator<Integer>() {
        @Override public int compare(Integer i, Integer j) {
            return key.get(i).compareTo(key.get(j));
        }
    });

    // Scan the new indices array and swap items to their new locations,
    // while remembering where original items stored.
    // Only swaps can be used since we do not know the type of the lists
    int[] prevSwaps = new int[indices.length];
    for (int i = 0; i < indices.length; i++) {
        int k = indices[i];
        while (i > k)
            k = prevSwaps[k];
        if (i != k) {
            prevSwaps[i] = k;
            for (List<?> list : lists)
                Collections.swap(list, i, k);
        }
    }
}

回答by sundar

I suggest you to create a class as below

我建议你创建一个类如下

class Dress {
  public int record;
  public String color;
  public String clothes;
}

Maintain the list of dresses as below

保持礼服列表如下

List<Dress> dressCollection = new ArrayList<Dress>();

Implement comparator based on color and clothes.

实现基于颜色和衣服的比较器。

List<Dress> resultBasedOnColor = Collections.sort(dressCollection, new Comparator<Dress>() {
   public int compareTo(Dress obj1, Dress obj2) {
     return obj1.color.compareTo(obj2.color);
 }

});

Left sorting based on clothes as exercise for question owner.

左排序基于衣服作为问题所有者的练习。

回答by 074Geodude

Thanks for the help guys.

谢谢你们的帮助。

I was so fixed on using arrays and sorting those arrays (since that's what was required of me), that I didn't even think about creating objects instead.

我非常专注于使用数组和对这些数组进行排序(因为这是我的要求),我什至没有考虑创建对象。

With this simple program, it'll allow you to create an object and sort the fields within the object. The colors and clothes were just an example I was using.

通过这个简单的程序,您可以创建一个对象并对对象中的字段进行排序。颜色和衣服只是我使用的一个例子。

Here's my completed code below:

这是我完成的代码如下:

// ColorClothes.java

import java.util.*;


public class ColorClothes
{
public int record;
public String color;
public String clothes;

public static void main(String[] args)
{
    Initialize();
}

public static void Initialize()
{
    ColorClothes item[] = new ColorClothes[4];

    item[0] = new ColorClothes();
    item[0].record = 0;
    item[0].color = "blue";
    item[0].clothes = "shoes";

    item[1] = new ColorClothes();
    item[1].record = 1;
    item[1].color = "yellow";
    item[1].clothes = "pants";

    item[2] = new ColorClothes();
    item[2].record = 2;
    item[2].color = "red";
    item[2].clothes = "boots";

    item[3] = new ColorClothes();
    item[3].record = 3;
    item[3].color = "black";
    item[3].clothes = "coat";

    System.out.println("Unsorted");

    for(int i = 0; i < item.length; i++)
    {
        System.out.println(item[i].record + "     " + item[i].color + "     " + item[i].clothes);
    }

    System.out.println("\nSorted By Color\n");

    Arrays.sort(item, new ColorComparator());

    for(int i = 0; i < item.length; i++)
    {
        System.out.println(item[i].record + "     " + item[i].color + "     " + item[i].clothes);
    }

    System.out.println("\nSorted By Clothes\n");

    Arrays.sort(item, new ClothesComparator());

    for(int i = 0; i < item.length; i++)
    {
        System.out.println(item[i].record + "     " + item[i].color + "     " + item[i].clothes);
    }

}

}// End class.

// ColorComparator.java

import java.util.Comparator;

class ColorComparator implements Comparator
{
public int compare(Object str1, Object str2)
{
    String str1Color = ((ColorClothes)str1).color;
    String str2Color = ((ColorClothes)str2).color;

    return str1Color.compareTo(str2Color);

}
}// End class.

// ClothesComparator.java

import java.util.Comparator;


class ClothesComparator implements Comparator
{
public int compare(Object str1, Object str2)
{
    String str1Clothes = ((ColorClothes)str1).clothes;
    String str2Clothes = ((ColorClothes)str2).clothes;

    return str1Clothes.compareTo(str2Clothes);

}
} // End class.

Console Output

控制台输出

Unsorted
0     blue     shoes
1     yellow     pants
2     red     boots
3     black     coat

Sorted By Color

3     black     coat
0     blue     shoes
2     red     boots
1     yellow     pants

Sorted By Clothes

2     red     boots
3     black     coat
1     yellow     pants
0     blue     shoes

I'll add another Comparator to allow sorting by record/integers later. I'll also condense the code more so it's not one big block, but I'm almost done with work for the day.

我将添加另一个比较器,以便稍后按记录/整数进行排序。我还将进一步压缩代码,使其不是一个大块,但我几乎完成了一天的工作。