[英]Get the indices of an array after sorting?
假設用戶輸入一個數組,例如:
Array = {France, Spain, France, France, Italy, Spain, Spain, Italy}
我知道它的長度
index
數組將是:
index = {0, 1, 2, 3, 4, 5, 6, 7}
現在,在使用Arrays.sort(Array);
對其進行Arrays.sort(Array);
后Arrays.sort(Array);
newArray
將類似於:
newArray = {France, France, France, Italy, Italy, Spain, Spain, Spain}
並且newIndex
將是:
newIndex = {0, 2, 3, 4, 7, 1, 5, 6}
問題是:如何從輸入數組中找到newIndex
?
提前致謝
不要對數組進行排序。 對索引數組進行排序,傳入一個比較器,該比較器通過將值用作數組中的索引來比較值。 所以你最終得到newIndex
作為排序的結果,從那里轉到實際項目的排序數組是微不足道的。
誠然,這意味着以自定義方式對整數數組進行排序 - 這意味着使用Integer[]
和標准 Java 庫,或者使用具有“IntComparator”接口的 3rd 方庫,該接口可以與sort(int[], IntComparator)
類型的方法。
編輯:好的,這是一個示例比較器。 為簡單起見,我假設您只想對“原始”字符串數組進行排序……而且我不會費心進行無效性測試。
public class ArrayIndexComparator implements Comparator<Integer>
{
private final String[] array;
public ArrayIndexComparator(String[] array)
{
this.array = array;
}
public Integer[] createIndexArray()
{
Integer[] indexes = new Integer[array.length];
for (int i = 0; i < array.length; i++)
{
indexes[i] = i; // Autoboxing
}
return indexes;
}
@Override
public int compare(Integer index1, Integer index2)
{
// Autounbox from Integer to int to use as array indexes
return array[index1].compareTo(array[index2]);
}
}
你會像這樣使用它:
String[] countries = { "France", "Spain", ... };
ArrayIndexComparator comparator = new ArrayIndexComparator(countries);
Integer[] indexes = comparator.createIndexArray();
Arrays.sort(indexes, comparator);
// Now the indexes are in appropriate order.
使用 Java 8 Stream API 實現這一點的簡潔方法,
final String[] strArr = {"France", "Spain", "France"};
int[] sortedIndices = IntStream.range(0, strArr.length)
.boxed().sorted((i, j) -> strArr[i].compareTo(strArr[j]) )
.mapToInt(ele -> ele).toArray();
TreeMap<String,Int> map = new TreeMap<String,Int>();
for( int i : indexes ) {
map.put( stringarray[i], i );
}
現在迭代 map.values() 以按排序順序檢索索引,並通過 map.keySet() 獲取字符串,或通過 map.entrySet() 獲取 String-index-Pairs。
如果有重復排序具有正值的原始 float 或 int 數組的場景,那么與使用任何比較器相比,如下所示的方法會產生更好的 (x3~x4) 速度:
long time = System.currentTimeMillis();
for (int i = 0; i < iters; i++) {
float[] array = RandomUtils.randomFloatArray(-1, 1, 3000);
long[] valueKeyPairs = new long[array.length];
for (int j = 0; j < array.length; ++j) {
valueKeyPairs[j] = (((long) Float.floatToIntBits(array[j])) << 32) | (j & 0xffffffffL);
}
Arrays.sort(valueKeyPairs);
/**Then use this to retrieve the original value and index*/
//long l = valueKeyPairs[j];
//float value = Float.intBitsToFloat((int) (l >> 32));
//int index = (int) (l);
}
long millis = System.currentTimeMillis() - time;
我根據@Skeet 的代碼做了以下內容。 我認為它更像是 OOPie。 我不知道。
public static <T extends Comparable<T>> List<Integer> sortIndex(List<T> in) {
ArrayList<Integer> index = new ArrayList<>();
for (int i = 0; i < in.size(); i++) {
index.add(i);
}
Collections.sort(index, new Comparator<Integer>() {
@Override
public int compare(Integer idx1, Integer idx2) {
return in.get(idx1).compareTo(in.get(idx2));
}
});
return index;
}
原始數組中的對象必須實現 Comparable 接口,而不是實現排序和索引的類具有用於不同對象的 Comparator 代碼。 似乎許多感興趣的對象都有自然排序,並且已經實現了 Comparable 接口。
public static void main(String[] args) {
List<Integer> a1 = new ArrayList<>(Arrays.asList(2, 3, 9, 4, 1));
// Just pass in the list to have its indexes sorted by the natural ordering
List<Integer> idx = sortIndex(a1);
List<Double> a2 = new ArrayList<>(Arrays.asList(1.0, 5.3, 5.2, -3.1, 0.3));
idx = sortIndex(a2);
List<numBits> a3 = new ArrayList<>();
for (int i = 0; i < 10; i++) {
a3.add(new numBits(i));
}
// If you need to sort the indexes of your own object, you must implement
// the Comparable Interface.
idx = sortIndex(a3);
}
static class numBits implements Comparable<numBits> {
private int a;
public numBits(int i) {
a = i;
}
public String toString() {
return Integer.toString(a);
}
// Sort by the total number of bits in the number.
@Override
public int compareTo(numBits that) {
if (Integer.bitCount(this.a) < Integer.bitCount(that.a))
return -1;
if (Integer.bitCount(this.a) > Integer.bitCount(that.a))
return 1;
return 0;
}
}
您可以這樣做的一種方法是將原始索引和國家/地區名稱包裝到一個單獨的類中。 然后根據名稱對 Array 進行排序。 這樣,您的原始索引將被保留。
乍一看是這樣映射它們
Map <Integer, String> map = new HashMap<Integer, String>();
map.put(0, "France");
map.put(1, "Spain");
map.put(2, "France");
然后按這樣的值對它們進行排序,然后您就可以知道它們的索引和值(鍵、值),只需打印地圖
Iterator mapIterator = map.keySet().iterator();
while (mapIterator .hasNext()) {
String key = mapIterator.next().toString();
String value = map.get(key).toString();
System.out.println(key + " " + value);
}
我找到了解決方案。
List<String> a = {b, a, d, c};
List<Integer> b = {2, 1, 4, 3};
如果a
排序
private void setsortb() {
List<String> beforeA = new ArrayList<>();
List<Integer> beforeB = new ArrayList<>();
beforeA.addAll(a);
beforeB.addAll(b);
a.sort();//change like this {a, b, c, d}
for(int i = 0; i < beforeA.size(); i++) {
int index = beforeA.indexOf(a.get(i));
b.set(i, beforeB.get(i));
}
}
像這樣
結果
a = {a, b, c, d}
b = {1, 2, 3, 4}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.