Home > Enterprise >  How to change an array list order based on another array list
How to change an array list order based on another array list

Time:11-05

Currently I have 2 array lists showing words and their frequency. So "the" has a frequency of 1, "I" has a frequency of 10 and so on.

  ArrayList<String> words = new ArrayList<>(Arrays.asList("the", "I", "false","too"));
        
  ArrayList<Integer> frequency = new ArrayList<>(Arrays.asList(1, 10, 5, 7));


  Collections.sort(frequency, Collections.reverseOrder());

What I want to do is sort them from highest word frequency to lowest, so I used Collections.sort to sort frequency from highest values to lowest. This gives me the expected result of

[10, 7, 5, 1]

But now I'm at a complete standstill has to how to sort the words ArrayList so that the indexes of each list still correspond to each other.

My desired output would be for the words arraylist would be.

["I", "too", "false", "the"]

Is there some kind of method within Collections that can accomplish this?

CodePudding user response:

You should sort the indices [0, 1, 2, 3] by frequency.get(i) and map the results with words.get(i) respectively.

ArrayList<String> words = new ArrayList<>(Arrays.asList("the", "I", "false","too"));
ArrayList<Integer> frequency = new ArrayList<>(Arrays.asList(1, 10, 5, 7));

List<String> sortedWords = IntStream.range(0, words.size())
    .boxed()
    .sorted(Collections.reverseOrder(Comparator.comparing(frequency::get)))
    .map(words::get)
    .collect(Collectors.toList());

System.out.println(sortedWords);

output:

[I, too, false, the]

CodePudding user response:

The task is quite trivial, if you use the correct data structure for it. For this particular task it is java.util.Map. Maps contain key-value pairs (mappings, entries). Then it becomes easy to sort words by frequency, without losing the mapping word -> frequency.

public class Test {

  public static void main(String[] args) {
    ArrayList<String> words = new ArrayList<>(Arrays.asList("the", "I", "false","too"));
    ArrayList<Integer> frequency = new ArrayList<>(Arrays.asList(1, 10, 5, 7));

    Map<String, Integer> wordFrequency = new HashMap<>();
    for (int i = 0; i < words.size(); i  ) {
      wordFrequency.put(words.get(i), frequency.get(i));
    }
    List<String> sortedByFrequency = wordFrequency.entrySet()
            .stream()
            .sorted((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()))
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());
    System.out.println(sortedByFrequency);
  }
}

Depending on how you populate the lists initially, you can directly populate the Map and not use the lists at all.

Map<String, Integer> wordFrequency = new HashMap<>();
wordFrequency.put("the", 1);
wordFrequency.put("I", 10);
//and so on

Another option would be to use intermediate object to contain the mapping word -> frequency.

public class Pair {

  private final String word;
  private final int frequency;

  //constructor
  //getters
}

Then map values in the list to this intermediate object, sort by frequency, extract words, collect.

List<String> sortedByFrequency = IntStream.range(0, words.size())
        .mapToObj(i -> new Pair(words.get(i), frequency.get(i)))
        .sorted(Comparator.comparing(Pair::getFrequency).reversed())
        .map(Pair::getWord)
        .collect(Collectors.toList());
System.out.println(sortedByFrequency);
  • Related