java 排序后获取数组的索引?

xjreopfe  于 2022-12-28  发布在  Java
关注(0)|答案(8)|浏览(252)

假设用户输入一个数组,例如:

Array = {France, Spain, France, France, Italy, Spain, Spain, Italy}

我知道它的长度
index数组将是:

index = {0, 1, 2, 3, 4, 5, 6, 7}

现在,使用Arrays.sort(Array);对其排序后
newArray将类似于:

newArray = {France, France, France, Italy, Italy, Spain, Spain, Spain}

并且newIndex将为:

newIndex = {0, 2, 3, 4, 7, 1, 5, 6}

问题是:如何从输入数组中找到newIndex

baubqpgj

baubqpgj1#

不要一开始就对数组进行排序,而是对索引数组进行排序,传入一个比较器,该比较器通过将值作为索引来比较数组中的值,所以最后得到newIndex作为排序的结果,从那里到实际项的排序数组是很简单的。
诚然,这意味着以自定义的方式对整数数组进行排序-这意味着使用Integer[]和标准Java库,或者使用具有“IntComparator”接口的第三方库,该接口可以与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.
h43kikqp

h43kikqp2#

使用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();
n6lpvg4x

n6lpvg4x3#

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。

yhqotfr8

yhqotfr84#

如果有一个重复排序带正值的基元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;
ux6nzvsh

ux6nzvsh5#

我根据@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;
}

不是实现排序和索引的类为不同的对象提供Comparator代码,而是原始数组中的对象必须实现Comparable接口,看起来很多感兴趣的对象都有自然的排序,并且已经实现了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;
    }
}
jm2pwxwz

jm2pwxwz6#

一种方法是将原始索引和国家名称 Package 到一个单独的类中,然后根据名称对Array进行排序。这样,原始索引将被保留。

gk7wooem

gk7wooem7#

第一眼看到的是这样的Map

Map <Integer, String> map = new HashMap<Integer, String>();
map.put(0, "France");
map.put(1, "Spain");
map.put(2, "France");

然后按值like that对它们进行排序,然后您可以知道它们的索引和值(键、值),只需打印Map

Iterator mapIterator = map.keySet().iterator();  

while (mapIterator .hasNext()) {  
     String key = mapIterator.next().toString();  
     String value = map.get(key).toString();  

     System.out.println(key + " " + value);  
}
mf98qq94

mf98qq948#

我找到了解决办法。

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}

相关问题