基于唯一集合 Java 中的列表整数元素创建 "ordinal" 簇
Creating "ordinal" clusters based on List Integer elements in Java based on unique set
我正在尝试使用整数列表中的数字创建从 1 开始的有序簇。
例如,如果我有一个列表整数,例如:[-1, 7, 99, 4, 5, 33, 6, 4, 77, 3, 7, 99, 2, 7],这些数字是算法返回的集群。该算法不会创建连续编号,如 1、2、3...,而是随机 "jump"。
所以我想要实现的或多或少是集群的清理版本。唯一的例外是上面列表中任何为 -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 而只映射一次?
问题出在这一行:
if (distinctIntegerList.get(i) == myListInteger.get(j))
您的列表中有整数类型。 ==
用于比较原始类型(int、long、double ..)。
比较引用类型(Integer、Double、Long)时应始终使用 equals 方法
将该行更改为
if (distinctIntegerList.get(i).equals(myListInteger.get(j)))
最好使用地图而不是列表来完成您的任务,这会使代码更具可读性:
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 开始的有序簇。
例如,如果我有一个列表整数,例如:[-1, 7, 99, 4, 5, 33, 6, 4, 77, 3, 7, 99, 2, 7],这些数字是算法返回的集群。该算法不会创建连续编号,如 1、2、3...,而是随机 "jump"。
所以我想要实现的或多或少是集群的清理版本。唯一的例外是上面列表中任何为 -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 而只映射一次?
问题出在这一行:
if (distinctIntegerList.get(i) == myListInteger.get(j))
您的列表中有整数类型。 ==
用于比较原始类型(int、long、double ..)。
比较引用类型(Integer、Double、Long)时应始终使用 equals 方法
将该行更改为
if (distinctIntegerList.get(i).equals(myListInteger.get(j)))
最好使用地图而不是列表来完成您的任务,这会使代码更具可读性:
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;
}
}