对数组进行排序并保留原始索引

Posted

技术标签:

【中文标题】对数组进行排序并保留原始索引【英文标题】:Sorting an array and keeping original index 【发布时间】:2017-07-12 23:54:18 【问题描述】:

我正在尝试制作一个对数组进行排序但跟踪其原始索引的程序。我不想更改原始数组,因此将其复制到 list[][] 中。

   public static void main(String[] args) 

    int array[] = 17, 10, 8, 13, 5, 7, 8, 30;
    int list[][] = new int[8][2];
    int temp1, temp2, index, max;

    for(int i=0;i<array.length; i++)
        list[i][0]=array[i];
        list[i][1]=i;
    

        for(int i=0; i <array.length-1; i++)
            max = list[i][0];
            index = i;

            for(int j = i+1; j<array.length;j++)
            if(max<list[j][0])
                max = list[j][0];
                index = j;

            
        
            temp1 = list[i][0];
            temp2 = list[i][1];

            list[i][0]=max;
            list[i][1] = index;

            list[index][0]=temp1;
            list[index][1]=temp2;




        
        for(int n=0; n<list.length;n++)
                System.out.println(list[n][0] + " " + list[n][1]);

        




所以它应该打印出来:

30 7

17 0

13 3

10 1

8 2

8 6

7 5

5 4

但是当我运行它时,它会打印:

30 7

17 7

13 3

10 7

8 6

8 7

7 7

5 4

有什么建议吗?

【问题讨论】:

为什么不把第二个数组变成一个包含数字和原始索引的元组? 【参考方案1】:

为什么不做一些漂亮干净的 OOP?

class Element implements Comparable<Element> 

    int index, value;

    Element(int index, int value)
        this.index = index;
        this.value = value;
    

    public int compareTo(Element e) 
        return this.value - e.value;
    

用法:

int array[] = 17, 10, 8, 13, 5, 7, 8, 30;

// Init the element list
List<Element> elements = new ArrayList<Element>();
for (int i = 0; i < array.length; i++) 
    elements.add(new Element(i, array[i]));


// Sort and print
Collections.sort(elements);
Collections.reverse(elements); // If you want reverse order
for (Element element : elements) 
    System.out.println(element.value + " " + element.index);

【讨论】:

【参考方案2】:

就我个人而言,我更喜欢 OOP——就像 Oneiros' 的回答。根据他的回答,我稍微修改了代码以更好地cohesion。

必需的导入

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

Oneiros' 类 - 已更改

class Element
    private int index;
    private int value;

    public Element(int index, int value)
        this.index = index;
        this.value = value;
    

    public int getValue()
        return this.value;
    

    @Override
    public String toString()
        return value + " " + index;
    

    public void print()
        System.out.println(this);
    

比较器

class NumberComparator implements Comparator<Element>
    @Override
    public int compare(Element a, Element b) 
        return b.getValue() - a.getValue(); // ASC: a - b or DESC: b - a
    

主要区别在于 Comparator 现在是一个类本身。这允许更高的可交换性,以防您想使用其他比较器。

用法

public class Main 
    // Holds the sorted numbers and their corresponding indexes
    private static List<Element> elements = new ArrayList<>();

    public static void main(String[] args) 
        // Original array
        int[] original = 17, 10, 8, 13, 5, 7, 8, 30;

        // Add elements to list for sorting
        for (int i = 0; i < original.length; i++) 
            elements.add(new Element(i, original[i]));
        

        // Actually sort the list
        elements.sort(new NumberComparator());

        // Print
        elements.forEach(System.out::println);
    

【讨论】:

【参考方案3】:

另一种实现方式。

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class MyMath 

    public static void main(String[] args) 
        int array[] =  17, 10, 8, 13, 5, 7, 8, 30 ;

        Map<Integer, Integer> m1= new HashMap<Integer, Integer>();
        int k=0;
        for(int i:array)
            m1.put(k++, i);
        
        m1= MyMath.sortByValues(m1);
        for (int key: m1.keySet())
             System.out.println(m1.get(key) + " " + key);  
          
       


    public static <K extends Comparable,V extends Comparable> Map<K,V> sortByValues(Map<K,V> map)
        List<Map.Entry<K,V>> entries = new LinkedList<Map.Entry<K,V>>(map.entrySet());

        Collections.sort(entries, new Comparator<Map.Entry<K,V>>() 

            @Override
            public int compare(Entry<K, V> o1, Entry<K, V> o2) 
                return o2.getValue().compareTo(o1.getValue());
            
        );

         Map<K,V> sortedMap = new LinkedHashMap<K,V>();

        for(Map.Entry<K,V> entry: entries)
            sortedMap.put(entry.getKey(), entry.getValue());
        

        return sortedMap;
    


【讨论】:

以上是关于对数组进行排序并保留原始索引的主要内容,如果未能解决你的问题,请参考以下文章

在C中排序后跟踪数组的原始索引

Swift 对数组进行排序并返回索引和元素的数组

如何对数组进行排序并返回配置单元中的索引?

如何按值对数组进行排序(排序)? *有一个转折*

python使用np.argsort对一维numpy概率值数据排序获取倒序索引获取的top索引(例如top2top5top10)索引二维numpy数组中对应的原始数据:原始数据概率最大的头部数据

python使用np.argsort对一维numpy概率值数据排序获取升序索引获取的top索引(例如top2top5top10)索引二维numpy数组中对应的原始数据:原始数据概率最小的头部数据