简体   繁体   中英

Sort a List in Dart based on how another List was sorted

I am trying to sort a list with reference to another list. Consider this example,

List<String> a = ["a", "b", "c"];
List<int> b = [2, 3, 1];

Now, I want the result to be like this,

a = ["c", "a", "b"];
b = [1, 2, 3];

How can I achieve this result?

You can achieve this by create a Map that holds the mappings for the letters to your numbers, ie 2 has a assigned to it, 3 has b etc.
Now you can sort your list normally and after that recreate your other list based on the mappings that you stored before sorting:

main() {
  List<String> letters = ["a", "b", "c"];
  final List<int> numbers = [2, 3, 1];

  final Map<int, String> mappings = {
    for (int i = 0; i < numbers.length; i++)
      numbers[i]: letters[i]
  };

  numbers.sort();

  letters = [
    for (int number in numbers) mappings[number]
  ];

  print(letters); // [c, a, b]
  print(numbers); // [1, 2, 3]
}

I used collection for for this example. This syntax for collection literals was introduced in Dart 2.3 .
Learn more .

You can easily turn this about and map the numbers to your letters instead. That would look like this:

main() {
  final List<String> letters = ["a", "b", "c"];
  List<int> numbers = [2, 3, 1];

  final Map<String, int> mapping = {
    for (int i = 0; i < letters.length; i++)
      letters[i]: numbers[i]
  };

  letters.sort((a, b) => b.compareTo(a));

  numbers = [
    for (String letter in letters) mapping[letter]
  ];

  print(letters); // [c, b, a]
  print(numbers); // [1, 3, 2]
}

Note that I sorted the letters in a descending order here by turning about the compareTo as well (by default a.compareTo(b) is used by List.sort ).

If your List s have duplicate elements, you won't be able to use a Map . I'd instead use package:tuple and then use the same approach of combining the two List s into a single List<Tuple2> , sorting that, and extracting the values:

import 'package:tuple/tuple.dart';

void main() {
  var a = ["a", "b", "c", "d"];
  var b = [2, 3, 1, 1];

  var combined = <Tuple2<int, String>>[
    for (var i = 0; i < b.length; i += 1) Tuple2(b[i], a[i]),
  ];

  combined.sort((tuple1, tuple2) => tuple1.item1.compareTo(tuple2.item1));

  for (var i = 0; i < combined.length; i += 1) {
    a[i] = combined[i].item2;
    b[i] = combined[i].item1;
  }

  print(a); // Prints: [c, d, a, b]
  print(b); // Prints: [1, 1, 2, 3]
}

I use this way to solve the problem:

    List<String> strings = ["a", "b", "c", "c"];
    List<int> numbers = [2, 3, 1, 0];
    List<int> storeNumbers = List.from(numbers);
    List<int> storeIndex = [];
//sorting numbers list
 numbers.sort((a, b) => a.compareTo(b));

 //get the index of numbers list elements before the sorting
 for (int i = 0; i < numbers.length; i++) {
      for (int j = 0; j < storeNumbers.length; j++) {
        if (numbers[i] == storeNumbers[j]) {
                     storeIndex.add(j);
        }
      }
    }
    
    //generate a new string list based on the indexes we get
    strings =
        List.generate(strings.length, (index) => strings[storeIndex[index]]);

    print(strings);//output:[c, c, a, b]
    print(numbers);//output:[0, 1, 2, 3]

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