【问题标题】:Sorting list based on another list's order [duplicate]根据另一个列表的顺序对列表进行排序[重复]
【发布时间】:2018-01-03 02:16:42
【问题描述】:

我需要对Person 对象列表进行排序(List<Person>,其中每个Person 对象都有一些属性,例如id(唯一)、name、age...等)。

排序顺序基于另一个列表。该列表包含一组Personid(已排序的List<String>)。

使用 Kotlin 或 Java 以与 id 列表相同的顺序订购 List<Person> 的最佳方式是什么。

例子:

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

有序 ID 列表:

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

排序后的Person 列表应该是:

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

如果Person 列表包含id 列表中未提及的任何id,则这些值应位于排序列表的末尾。


已编辑:这是我目前使用 Java 的方式。我希望有比这更好的方法:

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;
}

【问题讨论】:

  • 向我们展示您的代码。
  • 你已经尝试过什么来解决你的问题?
  • “最佳”方式是什么意思?
  • 您的数据集有多大?对于琐碎的情况,您还不如蛮力它。对于 id 列表中的每个项目,在 person 列表中找到相应的项目并附加到一个新列表中。如果数据集很大,则按 ID 升序对人员列表进行排序。然后做同样的事情,但使用二进制搜索来查找 person-by-id
  • 我认为最好不要对它进行物理排序。使用Person 的地图来存储您的人员。 Map&lt;Integer, Person&gt; 然后使用您已经排序的 ID 列表作为索引。

标签: java list sorting kotlin


【解决方案1】:

一个有效的解决方案是首先创建从ids 中的 ID(您想要的 ID 顺序)到该列表中的索引的映射:

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

然后按照id 在此映射中的顺序对您的people 列表进行排序:

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

注意:如果某人的 ID 不在 ids 中,他们将被放在列表的首位。要将它们放在最后,您可以使用nullsLast 比较器:

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

【讨论】:

  • nullsFirst 这里影响的是 null 人的顺序,而不是那些 orderById[id] 为 null 的人。要指定键的空顺序,您需要将可选的比较器传递给compareBy:people.sortedWith(compareBy(nullsFirst&lt;Int&gt;()) { orderById[it.id] })。并且该比较器是可选的,因为没有它,空值首先排序。
  • 不要为我工作!
【解决方案2】:

以下代码会将 Person 列表转换为 Map,其中键是 ID,值是 Person 对象本身。这个Map 将有助于快速查找。然后遍历 ID 列表,从 Map 获取值并添加到另一个 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)

输出

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

【讨论】:

    【解决方案3】:

    试试下面的代码。

     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 将具有您期望的值...

    【讨论】:

      【解决方案4】:

      我会做类似的事情(在伪代码中,因为我不知道你的代码是什么样子的)

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

      如果你有一个地图(id-> 人)而不是 listOfPersons,那么查找会更容易。

      【讨论】:

        猜你喜欢
        • 2018-09-15
        • 2012-08-27
        • 1970-01-01
        • 2013-09-17
        • 2023-02-08
        • 2013-09-12
        • 1970-01-01
        • 2022-11-16
        • 1970-01-01
        相关资源
        最近更新 更多