簡體   English   中英

java中重復數字的去重

[英]Deduplication of repeated numbers in java

我有一個<Double,Double>TreeMap 我正在嘗試減少所有連續重復值的 map。
即鍵,值

 (1.0, 1.0)
 (2.0, 1.0)
 (3.0, 1.0)
 (4.0, 1.0)
 (5.0, 2.0)
 (6.0, 2.0)
 (7.0, 2.0)
 (8.0, 1.0)
 (9.0, 1.0)
(10.0, 1.0)

減少到

 (1.0, 1.0)
 (4.0, 1.0)
 (5.0, 2.0)
 (7.0, 2.0)
 (8.0, 1.0)
(10.0, 1.0)

我可以通過

List<Double> uniqueValues = test.values().parallelStream().distinct()
    .collect(Collectors.toList());

我可以遍歷這些值以獲取值的鍵

List<Integer> uniqueKeys = test.entrySet().stream()
    .filter(entry -> Objects.equals(entry.getValue(), uniqueValue))
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

但是現在我對獲取每組重復值的起點和終點感到茫然。

對此有什么好的解決方案? 我雖然想獲得提供的密鑰,但問題出現在上面的示例中,其中重復的數字又回來了。

您可以將每個系列收集到單獨的列表中。 感謝LinkedList ,您可以輕松訪問最后一個元素並檢查它是否仍然是相同的值。 如果值發生變化,則創建新的LinkedList以收集下一個條目。

LinkedList<LinkedList<Map.Entry<Double,Double>>> linkedLists = new LinkedList<>();

test.entrySet().stream().forEach(e -> {
    if (linkedLists.isEmpty() || 
        ! linkedLists.getLast().getLast().getValue().equals(e.getValue())) {
        linkedLists.add(new LinkedList<>());
    }
    linkedLists.getLast().add(e);
});

System.out.println(linkedLists);

之后,您可以將其更改為最終列表

System.out.println(linkedLists.stream()
    .flatMap(ll -> Arrays.asList(ll.getFirst(), ll.getLast()).stream())
    .collect(Collectors.toList()));

或 map 保留訂單

System.out.println(linkedLists.stream()
    .flatMap(ll -> Arrays.asList(ll.getFirst(), ll.getLast()).stream())
    .collect( Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
        (a1, a2) -> a1, () -> new LinkedHashMap<>())));

使用列表而不是輸入值的 map 的實現:

    final List<Double> input = getInputList();

    final Map<Integer, Double> result = new LinkedHashMap<>();
    if (input.isEmpty()) {
        return result;
    }

    boolean firstOccurrence = true;
    for (int i = 0; i < input.size() - 1; i++) {
        final Double current = input.get(i);
        final Double next = input.get(i + 1);
        if (firstOccurrence || !current.equals(next)) {
            result.put(i, current);
        }
        firstOccurrence = !current.equals(next);
    }
    result.put(input.size() - 1, input.get(input.size() - 1));

首先,我首先要說的是,您不應該使用 Double 作為 Map 中的密鑰。 更多詳細信息: HashMap 中的雙倍

然后,這是一個帶有Map<Integer, Integer>的示例以簡化邏輯。 您需要將其調整為Map<Double, Double>

邏輯是第一個和最后一個 map 條目將始終在結果 map 中。 所以你只需要過濾掉中間的那些(索引 1 到 map 大小 -1)。 只是跳過與前一個或下一個具有相同值的那些

For循環版本

// get the sorted list of keys
List<Integer> keys = new ArrayList<>(map.keySet());
Collections.sort(keys);

List<Integer> resultKeys = new ArrayList<>();
// first key will always be in the result map, add it
resultKeys.add(keys.get(0));
// for each following key, add if the value is different from both previous or next
for (int i = 1; i < keys.size()-1; i++) {
    Integer key = keys.get(i);
    Integer value = map.get(key);

    Integer previousKey = keys.get(i-1);
    Integer previousValue = map.get(previousKey);

    Integer nextKey = keys.get(i+1);
    Integer nextValue = map.get(nextKey);

    if(previousValue.intValue() != value.intValue() || nextValue.intValue() != value.intValue()) {
        resultKeys.add(key);
    }
}

// last key will always be in the result map, add it
resultKeys.add(keys.get(keys.size()-1));

// make a map out of you list
Map<Integer, Integer> resultMap = resultKeys.stream()
        .collect(Collectors.toMap(k -> k, map::get));

Map<Integer, Integer> resultTreeMap = new TreeMap<>();
resultTreeMap.putAll(resultMap);

Lambda版

// get the sorted list of keys
List<Integer> keys = new ArrayList<>(map.keySet());
Collections.sort(keys);

Map<Integer, Integer> resultMap = 
        IntStream.range(1, keys.size()-1)
        .boxed()
        .map(i -> setToNullIfNotKept(keys, i))
        .filter(Objects::nonNull)
        .collect(Collectors.toMap(k -> k, map::get));

// first key will always be in the result map, add it
resultMap.put(keys.get(0), map.get(keys.get(0)));
// last key will always be in the result map, add it
Integer lastKey = keys.get(keys.size() - 1);
resultMap.put(lastKey, map.get(lastKey));

Map<Integer, Integer> resultTreeMap = new TreeMap<>();
resultTreeMap.putAll(resultMap);

取消不需要的索引的實用方法:

private static Integer setToNullIfNotKept(List<Integer> keys, Integer i) {
    Integer key = keys.get(i);
    Integer value = map.get(key);

    Integer previousKey = keys.get(i-1);
    Integer previousValue = map.get(previousKey);

    Integer nextKey = keys.get(i+1);
    Integer nextValue = map.get(nextKey);

    if(previousValue.intValue() != value.intValue() || nextValue.intValue() != value.intValue()) {
        return key;
    }
    return null;
}

Output

鑒於輸入 map:

Map<Integer, Integer> map = new TreeMap<>();
map.put(1, 1);
map.put(2, 1);
map.put(3, 1);
map.put(4, 1);
map.put(5, 2);
map.put(6, 2);
map.put(7, 2);
map.put(8, 1);
map.put(9, 1);
map.put(10, 1);

它們都是 output 以下 Map:

{1=1, 4=1, 5=2, 7=2, 8=1, 10=1}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM