Как отсортировать несколько массивов в java
Я пытаюсь сортировать три массива по лексикографическому порядку. Массивы связаны друг с другом общим массивом. Это проще объяснить, если я продемонстрирую:
int[] record = new int[4];
String [] colors = {"blue", "yellow", "red", "black"};
String [] clothes = {"shoes", "pants", "boots", "coat"};
При печати на консоли я хотел бы, чтобы они были помещены в три столбца, похожие на ниже:
Unsorted:
Record Color Clothes
0 blue shoes
1 yellow pants
2 red boots
3 black coat
Отсортировано по цвету:
Record Color Clothes
3 black coat
0 blue shoes
2 red boots
1 yellow pants
Отсортировано по одежде:
Record Color Clothes
2 red boots
3 black coat
1 yellow pants
0 blue shoes
Я нашел предыдущий ответ, похожий на мой сценарий, но он сравнивал целые числа вместо строк, и у меня возникли проблемы с использованием метода compareTo()
и Arrays.sort()
для получения нужного результата.
Любая помощь будет оценена!
Ответы
Ответ 1
Так как Record
, Color
и Clothes
кажутся совпадающими, я бы предложил их объединить в пользовательский объект, например
public class ClothesItem {
int record;
String color;
String clothes;
}
Затем вы можете сделать разные Comparator
, чтобы выполнить различные варианты сортировки.
Если вам нужно сохранить текущую структуру с несколькими массивами, @Jherico имеет решение для сортировки здесь, которое получает массив отсортированных индексов, что должно сделать его тривиальным чтобы получить желаемый результат.
Ответ 2
В некоторых случаях нет смысла создавать новый класс только для сортировки.
Здесь используется функция, которая может использоваться для сортировки любого количества произвольно типизированных списков (List<?>
) на основе списка ключей (List<T implements Comparable>
). Идеальный пример здесь.
Использование
Вот пример того, как вы можете использовать эту функцию для сортировки нескольких списков произвольных типов:
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);
Выход:
// 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]
код
Пример 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));
}
ПРИМЕЧАНИЕ. Время работы O(mlog(m) + mN)
, где m
- длина списка, а N
- количество списков. Обычно m >> N
, поэтому время работы не более важно, чем сортировка только клавиши O(mlog(m))
.
Ответ 3
Я не уверен в сортировке сразу нескольких массивов; глядя на используемый вами случай использования, это выглядит как соперник, в котором все 3 атрибута могут быть объединены в объект, а затем массив объектов может быть отсортирован несколькими способами.
Вы уверены, что вам нужно иметь 3 массива?
Может ли массив ColoredCloth
работать для вас:
class ColoredCloth implements Comparable<ColoredCloth>{
int id;
String color;
String cloth;
}
и определите пару Comparators
для сортировки по color
и cloth
.
Ответ 4
Хорошо, вот как это выглядит в окончательной форме.
// 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.
Консольный выход
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
Ответ 5
Сортировка массивов напрямую. Индексируйте все свои массивы и сортируйте только индексный массив нужного массива. Взгляните на решение в SO post. Это будет поддерживать ваши массивы. Я не уверен, легко ли экстраполировать это на сортировку N-массивов при синхронизации, но он должен дать вам представление о том, как подойти к проблеме, если вы хотите придерживаться того, что ваши данные распределены в нескольких массивах. Как уже отмечалось несколькими людьми, группировка данных в одном объекте является хорошим подходом.
Ответ 6
Вот как я сортирую два или более строковых массива одинаковой длины, так что первый массив упорядочен, а остальные массивы соответствуют этому порядку:
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 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;
}
Если вы хотите сделать это с помощью массивов других типов, вам нужно будет немного реорганизовать это. Альтернативно, для целочисленного массива, который нужно сортировать вместе со строковыми массивами, вы можете преобразовать целые числа в строки.
Ответ 7
Я предлагаю вам создать класс ниже
class Dress {
public int record;
public String color;
public String clothes;
}
Поддерживайте список платьев ниже
List<Dress> dressCollection = new ArrayList<Dress>();
Внедрить компаратор на основе цвета и одежды.
List<Dress> resultBasedOnColor = Collections.sort(dressCollection, new Comparator<Dress>() {
public int compareTo(Dress obj1, Dress obj2) {
return obj1.color.compareTo(obj2.color);
}
});
Левая сортировка, основанная на одежде как упражнение для владельца вопроса.
Ответ 8
Поместите данные в пользовательский класс, например @SiB:
class ColoredClothes {
int id;
String color;
String cloth;
}
Затем поместите каждый экземпляр этого класса в TreeMap с цветом в качестве ключа (или название ткани в зависимости от того, что вы хотите отсортировать):
TreeMap<String,ColoredClothes> sortedCloth= new TreeMap<String,ColoredClothes>();
//loop through arrays and put new ColoredClothes into Map
Затем получите отсортированные значения следующим образом:
Collection<ColoredClothes> values = sortedCloth.values();
Вы можете выполнить итерацию через них, используя values.iterator()
Ответ 9
Спасибо за помощь ребятам.
Я был так уверен в использовании массивов и сортировке этих массивов (с тех пор как это требовалось от меня), что я даже не думал о создании объектов.
С помощью этой простой программы она позволит вам создать объект и отсортировать поля внутри объекта. Цвета и одежда были просто примером, который я использовал.
Здесь мой код:
// 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.
Консольный выход
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
Я добавлю еще один компаратор, чтобы позже сортировать по записи/целям. Я также буду конденсировать код больше, так что это не один большой блок, но я почти закончил работу в течение дня.
Ответ 10
Как и другие, проще было бы сортировать коллекцию объектов, а не сортировать три массива синхронно.
Если по какой-либо причине вам приходится придерживаться сортировки нескольких массивов, можно использовать следующий подход: идея состоит в реализовать собственный вариант списка массивов, который поддерживается тремя массивами вместо одного.
import java.util.AbstractList;
import java.util.Collections;
public class SortMultipleArrays extends AbstractList {
//object representing tuple from three arrays
private static class ClothesItem implements Comparable<ClothesItem> {
int record;
String color;
String clothes;
public ClothesItem(int record, String color, String clothes) {
this.record = record;
this.color = color;
this.clothes = clothes;
}
@Override
public int compareTo(ClothesItem o) {
return this.color.compareTo(o.color); //sorting by COLOR
}
}
private int[] records;
private String[] colors;
private String[] clothes;
public SortMultipleArrays(int[] records, String[] colors, String[] clothes) {
this.records = records;
this.colors = colors;
this.clothes = clothes;
}
@Override
public Object get(int index) {
return new ClothesItem(records[index], colors[index], clothes[index]);
}
@Override
public int size() {
return records.length;
}
@Override
public Object set(int index, Object element) {
ClothesItem item = (ClothesItem) element;
ClothesItem old = (ClothesItem) get(index);
records[index] = item.record;
colors[index] = item.color;
clothes[index] = item.clothes;
return old;
}
public static void main(String[] args) {
int[] record = {0,1,2,3};
String[] colors = {"blue", "yellow", "red", "black"};
String[] clothes = {"shoes", "pants", "boots", "coat"};
final SortMultipleArrays multipleArrays = new SortMultipleArrays(record, colors, clothes);
Collections.sort(multipleArrays);
System.out.println("Record Color Clothes");
for (int i = 0; i < record.length; i++) {
System.out.println(String.format("%8s %8s %8s", record[i], colors[i], clothes[i]));
}
}
}
Эта реализация основана на AbstractList, которая упрощает реализацию интерфейса List, необходимого для Collections.sort(...).
Обратите внимание, что в этой реализации может быть скрытая неэффективность: методы get (...) и set (...) создают экземпляр объекта-обертки, который может вызвать слишком много объектов, созданных при сортировке больших массивов.
Ответ 11
Понравилась идея @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);
}
}
}
Ответ 12
import java.util.Arrays;
Arrays.sort (int [])
Arrays.sort (String [])
это отсортирует массив строк.