Создание «порядковых» кластеров на основе элементов List Integer в Java на основе уникального набора - PullRequest
2 голосов
/ 28 октября 2019

Я пытаюсь создать упорядоченные кластеры, начиная с 1, используя числа в целочисленном списке.

Например, если у меня есть List Integer, например: [-1, 7, 99, 4, 5, 33, 6, 4, 77, 3, 7, 99, 2, 7], эти числаявляются кластерами, возвращаемыми алгоритмом. Алгоритм не будет создавать последовательную нумерацию, такую ​​как 1, 2, 3 ..., а скорее будет "прыгать" случайным образом.

Так что я хочу достичь более или менее очищенной версии кластеров. Единственное исключение состоит в том, что любое число в приведенном выше списке, равное -1, останется -1 в новом списке упорядоченных пронумерованных кластеров.

Чтобы проиллюстрировать это, предположим, что в приведенном выше списке я создаю набор уникальныхэлементы: {-1, 2, 3, 4, 5, 6, 7, 33, 77, 99} для этих уникальных кластеров, я хотел бы создать новую нумерацию, например, изменить набор, чтобы сказать {-1, 1,2, 3, 4, 5, 6, 7, 8, 9}, чтобы заменить предыдущий набор, сохранив -1 без изменений. Каждый индекс в предыдущем наборе соответствует индексу в новом наборе.

Имея этот новый набор, я хочу затем запустить List Integer и соответственно обновить его. Итак, для приведенного выше примера у меня будет: [-1, 6, 9, 3, 4, 7, 5, 3, 8, 2, 6, 9, 1, 6].

Что я уже сделал?

import java.util.*;

public class testing {
    public static void main(String[] args) {

    int[] myIntArray = new int[]{-1, 1, 2, 3, 4, 5, 5, -1, 7, 5, 9, 5, 5, 10,
            4, 14, -1, 5, 5, 5, 5, 5, 14, 5, 22, 5, 5, 25, 5, 22, 22, 5, 5, 5, 4, 5, 4, 7, 5, 5, 14, 14, 5,
            5, 22, 9, 2, 5, 22, -1, 47, 5, 5, 5, 5, 5, 4, -1, -1, 5, 5, 22, 5, 5, 5, 9, 5, 5, 5, 5, 65, 5,
            5, 5, 5, 14, 5, 10, 5, -1, 5, 22, 5, 14, 14, 5, 5, 5, 5, 5, 22, 5, 5, 5, 5, 5, -1, -1, 90, 22,
            -1, 92, 47, -1, 65, -1, 47, -1, 5, 1, -1, 7, 47, 92, -1, 9, -1, 9, -1, 103, 47, 3, 14, 107, 1,
            92, -1, 4, -1, 4, 14, -1, 9, -1, -1, 22, -1, 9, 22, 92, 25, 92, 9, 14, -1, 92, 103, 47, 4, -1,
            22, 9, 92, 47, -1, 47, 9, 7, 107, -1, -1, 47, 9, 14, 4, 47, -1, 22, 4, 22, 9, 9, 90, -1, -1, 4,
            4, 22, 22, 103, 47, 47, -1, -1, 9, 14, 9, 4, 4, 22, 22, 159, 9, 103, 4, 22, 4, 159, 90, 4};

    List<Integer> myListInteger = new ArrayList<Integer>(myIntArray.length);

    // passing values to myListInteger from myIntArray
    for (int i : myIntArray) {
        myListInteger.add(i);
    }

    // get distinct numbers in myListInteger: Set
    Set<Integer> distinctNumbersSet = new HashSet<Integer>(myListInteger);

    // convert to List
    List<Integer> distinctIntegerList = new ArrayList<>();
    for (Integer i: distinctNumbersSet) {
        distinctIntegerList.add(i);
    }

    // index to start numbering unique values
    int index = 1;
    boolean increaseIndex = false;


    for (int i = 0; i < distinctIntegerList.size(); i++) {
        for (int j = 0; j < myListInteger.size(); j++ ) {
            if (myListInteger.get(j) == -1) {
                continue;
            }

            if (distinctIntegerList.get(i) == myListInteger.get(j)) {
                myListInteger.set(j, index);
                increaseIndex = true;
                continue;
            }
        }
        if (increaseIndex == true) {
            index++;
            increaseIndex = false;
        }

    }

    // after update the myListInteger, I can get distinct sets again
    Set<Integer> distinctSetAfterUpdate = new HashSet<Integer>(myListInteger);

    System.out.println(myListInteger); // there is a 159 almost at the end, while it is expected that it should be 18

    for (Integer ind: distinctSetAfterUpdate) {
        System.out.println(ind + ": " +  Collections.frequency(myListInteger, ind));
    }



    }
}

Проблема, которую я получаю

Самый высокий кластер в списке: 159, который появляется дважды, не собираетсяновый кластер 18 ... Если я попытаюсь визуализировать распределение на новом отображении, каким-то образом этот 159 будет выглядеть как кластер с 1 значением, а 18 - с 1 тоже ... в то время как на основе моей логики в коде это новое отображение кластера никогда не должно превышать размер набора.

Поэтому мой текущий вывод для визуализации распределения:

-1: 33
1: 3
2: 2
3: 2
4: 17
5: 56
6: 4
7: 16
8: 2
9: 12
10: 19
11: 2
12: 12
13: 2
14: 3
15: 7
16: 4
17: 2
18: 1
159: 1

, а я хочу получить

-1: 33
1: 3
2: 2
3: 2
4: 17
5: 56
6: 4
7: 16
8: 2
9: 12
10: 19
11: 2
12: 12
13: 2
14: 3
15: 7
16: 4
17: 2
18: 2

Любая помощь, пытаясь понять, почему мой код не отображает 159 дважды в 18, а только один раз?

Ответы [ 2 ]

1 голос
/ 28 октября 2019

Было бы лучше использовать карты для вашей задачи вместо списков, что делает код немного читабельным:

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.stream.Collectors;

public class MainData {

    static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {

        int[] myIntArray = new int[]{-1, 1, 2, 3, 4, 5, 5, -1, 7, 5, 9, 5, 5, 10,
            4, 14, -1, 5, 5, 5, 5, 5, 14, 5, 22, 5, 5, 25, 5, 22, 22, 5, 5, 5, 4, 5, 4, 7, 5, 5, 14, 14, 5,
            5, 22, 9, 2, 5, 22, -1, 47, 5, 5, 5, 5, 5, 4, -1, -1, 5, 5, 22, 5, 5, 5, 9, 5, 5, 5, 5, 65, 5,
            5, 5, 5, 14, 5, 10, 5, -1, 5, 22, 5, 14, 14, 5, 5, 5, 5, 5, 22, 5, 5, 5, 5, 5, -1, -1, 90, 22,
            -1, 92, 47, -1, 65, -1, 47, -1, 5, 1, -1, 7, 47, 92, -1, 9, -1, 9, -1, 103, 47, 3, 14, 107, 1,
            92, -1, 4, -1, 4, 14, -1, 9, -1, -1, 22, -1, 9, 22, 92, 25, 92, 9, 14, -1, 92, 103, 47, 4, -1,
            22, 9, 92, 47, -1, 47, 9, 7, 107, -1, -1, 47, 9, 14, 4, 47, -1, 22, 4, 22, 9, 9, 90, -1, -1, 4,
            4, 22, 22, 103, 47, 47, -1, -1, 9, 14, 9, 4, 4, 22, 22, 159, 9, 103, 4, 22, 4, 159, 90, 4};
        //distinct values of your array collected to list
        List<Integer> myListInteger = Arrays.stream(myIntArray).boxed().distinct().sorted()
                                            .collect(Collectors.toList());

        System.out.println(myListInteger);

        //map your unique values to there index, except -1
        Map<Integer, Integer> indexToUniqueValue = new HashMap<>();
        indexToUniqueValue.put(-1, -1);

        for (int i = 1; i < myListInteger.size(); i++) {
            indexToUniqueValue.put(i, myListInteger.get(i));
        }

        System.out.println(indexToUniqueValue);

        //map the indexes to frequency in your original array
        Map<Integer, Integer> indexToFrequency = new HashMap<>();
        for (Map.Entry<Integer, Integer> entry : indexToUniqueValue.entrySet()) {
            indexToFrequency.put(entry.getKey(), countFreq(entry.getValue(), myIntArray));
        }
        System.out.println(indexToFrequency);
    }

    private static Integer countFreq(Integer value, int[] myIntArray) {
        int count = 0;
        for (int i : myIntArray) {
            if (i == value) {
                count++;
            }
        }
        return count;
    }
}
1 голос
/ 28 октября 2019

Проблема в этой строке:

if (distinctIntegerList.get(i) == myListInteger.get(j))

В ваших списках есть целочисленные типы. == используется для сравнения примитивных типов (int, long, double ..). Вы всегда должны использовать метод equals при сравнении ссылочных типов (Integer, Double, Long)

Измените эту строку на

if (distinctIntegerList.get(i).equals(myListInteger.get(j)))
...