简体   繁体   中英

How to sort a collection based on a custom list

I have a number of lists.. in Scala or Java. List looks like this
List({cat, toronto}, {dog, vancouver}, {mouse, calgary} ... ) . Assume {cat, toronto} is an object of two strings. I need to sort these lists based on another criteria which is also a list, for example>> List(dog, cat, mouse) . As you can see, the sort criteria has no particular logic or natural sort order.
I understand it is always possible to use brute force approach. That is what I want to avoid. I want to sort like this >> myList1.sort(listCriteria) , and then myList2.sort(listCriteria) , and so on. Is there any way to do this? Thanks.

Not sure I understand the question, but it seems you just want to map a list of keys to a list of key-value pairs. Like

val in   = List(("cat", "toronto"), ("dog", "vancouver"), ("mouse", "calgary"))
val dict = in.toMap

def sort(keys: List[String]): List[(String, String)] = 
  keys.map(key => key -> dict(key))

sort(List("dog", "cat", "mouse"))

res3: List[(String, String)] = List((dog,vancouver), (cat,toronto), (mouse,calgary))

You can create a HashMap that maps each string from the criterion list to its position and then create a comparator that gets values from the HashMap and compares those. This way, a comparison requires O(1) time (on average).

You can create a comparator/lambda expression that compares elements by their index in your second list. Here's a plain java approach:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MapSort {

    private static class MyObject {
        final String first;
        final String second;

        public MyObject(String first, String second) {
            this.first = first;
            this.second = second;
        }

        @Override
        public String toString() {
            return this.first + "/" + this.second;
        }
    }

    public static void main(String[] args) {
        List<String> desiredOrder = Arrays.asList("dog", "cat", "mouse");
        List<MyObject> listToBeSorted = new ArrayList<>();
        listToBeSorted.add(new MyObject("cat", "toronto"));
        listToBeSorted.add(new MyObject("dog", "vancouver"));
        listToBeSorted.add(new MyObject("mouse", "calgary"));

        System.out.println(listToBeSorted);

        listToBeSorted.sort((o1, o2) -> desiredOrder.indexOf(o1.first) - desiredOrder.indexOf(o2.first));

        System.out.println(listToBeSorted);
    }
}

Output:

[cat/toronto, dog/vancouver, mouse/calgary]
[dog/vancouver, cat/toronto, mouse/calgary]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM