Search code examples
javalisttemplatesintegercomparator

One list acts as a template to sort another list


Lets say there are two lists:

List<Integer> listA = Arrays.asList(1,2,3,4,5,6,7,6,5,4,3,2,1,0); This list is a template for sorting another listB.

List<Integer> listB = Arrays.asList(0,106,107,101,105,102,102,103,104,106,105,103,101,104); This list on the other hand is unsorted.

The final list lets say listC should be having the order (101,102,103,104,106,107,106,105,104,103,102,101,0)? I am using comparators but it fails for different usecases?

public class JavaComparators {
    public static void main(String[] args) {
        
        List<Integer> listA = Arrays.asList(1,2,3,4,5,6,7,6,5,4,3,2,1,0);
        List<Integer> listB = Arrays.asList(0,106,107,101,105,102,102,103,104,106,105,103,101,104);
        
        System.err.println(listA);
        System.err.println(listB);

        // Create a set of elements present in listB for faster lookup
        Set<Integer> setB = new HashSet<>(listB);

        // Sort listA based on the index in listB or use a default index if not present
        listB.sort(Comparator.comparingInt(a -> {
            int index = listA.indexOf(a);
            
            if (index == -1) {
                // If the element is not in listB, check for nearby values
                int indexPlusOne = listA.indexOf(a + 100);
                int indexMinusOne = listA.indexOf(a - 100);

                if (indexPlusOne != -1) {
                    return indexPlusOne;
                } else if (indexMinusOne != -1) {
                    return indexMinusOne;
                } else {
                    // Use a default index if not present in listB or nearby
                    return Integer.MAX_VALUE;
                }
            }

            return index;
        }));

        System.err.println("Rearranged listB: " + listB);
    }
}

This is what I tried and this is the solution that I get, which is incorrect

[1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0]
[0, 106, 107, 101, 105, 102, 102, 103, 104, 106, 105, 103, 101, 104]
Rearranged listB: [101, 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 0]

Solution

  • I think, this code may help you

    public class Main {
        public static void main(String[] args) {
            List<Integer> listA = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0);
            List<Integer> listB = Arrays.asList(0,106,107,101,105,102,102,103,104,106,105,103,101,104);
    
            // ensure, that sizes are equal
            assert (listA.size() == listB.size());
    
            // sort for better mapping
            List<Integer> listAValues = listA.stream().sorted().toList();
            List<Integer> listBValues = listB.stream().sorted().toList();
    
            // map to ensure, that template completes
            Map<Integer, Integer> template = new HashMap<>();
            Set<Integer> processedB = new HashSet<>();
            for (int i = 0; i < listAValues.size(); i++) {
                Integer key = listAValues.get(i);
                Integer value = listBValues.get(i);
                if (template.containsKey(key)) {
                    assert(template.get(key).equals(value));
                } else {
                    assert(!processedB.contains(value));
                    template.put(key, value);
                    processedB.add(value);
                }
            }
    
            // rearrange
            List<Integer> rearrangedListB = listA
                    .stream()
                    .map(template::get)
                    .toList();
            System.err.println("Rearranged listB: " + rearrangedListB);
        }
    }
    

    I map values from A to B + ensure, that there is a correct number of every value. After I've done this I rearrange List B.

    This is, what code printed for me

    Rearranged listB: [101, 102, 103, 104, 105, 106, 107, 106, 105, 104, 103, 102, 101, 0]