Sorting a list based on another list

I need to sort a list of objects Person

( List<Person>

where each object Person

has several attributes, such as the id

(unique) name

, age

... etc).

The sort order is based on a different list. This list contains the set Person

id

(A List<String>

, which is already sorted).

What is the best way to order List<Person>

in the same order as a list id

using Kotlin or Java.

Example:

List Person {
("ID1","PERSON1",22,..), ("ID-2","PERSON2",20,..) ), ("ID-3","PERSON3",19,..),…..
}

      

List of ordered identifiers:

List of ID {("ID2"), ("ID1"),("ID3")….}

      

The sorted Person

list should be:

List PERSON {
 ("ID-2","PERSON 2",20,..) ), ("ID1","PERSON 2",22,..),  ("ID-3","PERSON 2",19,..),…..
}

      

If the list Person

contains anything id

that is not in the list id

, then these values ​​must be at the end of the sorted list.


Edited: This is my current way in Java. I hope for a better way than this:

public static List<Person> getSortList(List <Person> unsortedList, List<String> orderList){

    if(unsortedList!=null && !unsortedList.isEmpty() && orderList!=null && !orderList.isEmpty()){
        List sortedList = new ArrayList<OpenHABWidget>();
        for(String id : orderList){
            Person found= getPersonIfFound(unsortedList, id); // search for the item on the list by ID
            if(found!=null)sortedList.add(found);       // if found add to sorted list
            unsortedList.remove(found);        // remove added item
        }
        sortedList.addAll(unsortedList);        // append the reaming items on the unsorted list to new sorted list
        return sortedList;
    }
    else{
        return unsortedList;
    }

}

public static Person getPersonIfFound(List <Person> list, String key){
    for(Person person : list){
        if(person.getId().equals(key)){
            return person;
        }
    }
    return null;
}

      

+3


source to share


4 answers


I would do something like (in pseudocode, since I don't know what your code looks like)

listOfPersons = [{2,Bob},{3,Claire},{1,Alice}]
orderList = [1,3,2]
sortedList = []
for(id in orderList)
    person = listOfPersons.lookup(id)
    sortedList.add(person)  

      



And the search will be easier if you have a card (id-> person) and not listOfPersons.

+1


source


An efficient solution is to first create a mapping from ID in ids

(your desired order of IDs) to an index in that list:

val orderById = ids.withIndex().associate { it.value to it.index }

      

And then sort your list people

in order of them id

in this mapping:



val sortedPeople = people.sortedBy { orderById[it.id] }

      

Note. If the person has an identifier that is not in ids

, it will be placed first in the list. To put them one last time, you can use a nullsLast

comparator:

val sortedPeople = people.sortedWith(compareBy(nullsLast<String>) { orderById[it.id] })

      

+1


source


Try the below code.

 Map<String, Person> personMap=new HashMap<>(); // create a map with key as ID and value as Person object
List<String> orderList=new ArrayList<>();  // create a list or array with ID order
List<Person> outputList=new ArrayList<>(); //list to hold sorted values

//logic

    // to sort Person based on ID list order
    for (String order : orderList) {
      if(personMap.containsKey(order)){
        outputList.add(personMap.get(order));
        personMap.remove(order);
      }
    }

  // logic to add the Person object whose id is not present in ID order list
    for (Entry<String, Person> entry : personMap.entrySet())
    {
      int lastIndex=outputList.size();
      outputList.add(lastIndex, entry.getValue());
      lastIndex++;
    }

      

outputList

Will now have the values ​​you expect ...

0


source


The following code converts the list Person to Map

, where the key will be the identifier and the value will be the Person object itself. This Map

will help you find quickly. Then go through the list of IDs to get the value from Map

and appended to another List

.

fun main(args: Array<String>) {
  // List of ID
  val listId = listOf(2, 1, 3)

  val list = listOf(Person(id = 1, name = "A"),
        Person(id = 2, name = "B"),
        Person(id = 3, name = "C"))

  val map: Map<Int, Person> = list.associateBy ({it.id}, {it})

  val sortedList = mutableListOf<Person>()

  listId.forEach({
      sortedList.add(map[it]!!)
  })

  sortedList.forEach({
     println(it)
  })
}

data class Person(val id: Int, val name: String)

      

Output

Person(id=2, name=B)
Person(id=1, name=A)
Person(id=3, name=C)

      

0


source







All Articles