查找列表中的所有重复项并为其添加一个数字

时间:2014-03-17 14:23:51

标签: java

我想在列表中找到所有重复项,并将其更改为下一个: {"a", "b", "c", "a", "b"}

{"a1", "b1", "c", "a2", "b2"}

我知道如何在列表中找到副本,但是我很难为每个相同的字符串添加出现次数。

4 个答案:

答案 0 :(得分:2)

使用Map<String, List<Integer>>,它将包含每个元素所在的索引列表。创建此类映射后,只需检查哪个元素包含多个索引,然后根据需要更新每个元素。

String[] arr = { "a", "b", "c", "a", "b" };

Map<String, List<Integer>> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
    if (map.containsKey(arr[i])) {
        map.get(arr[i]).add(i);
    } else {
        List<Integer> list = new ArrayList<>();
        list.add(i);
        map.put(arr[i], list);
    }
}

for (Map.Entry<String, List<Integer>> entry : map.entrySet()) {
    if (entry.getValue().size() > 1) {
        int counter = 1;
        for (int i : entry.getValue()) {
            arr[i] += counter++;
        }
    }
}
System.out.println(Arrays.toString(arr));

输出:[a1, b1, c, a2, b2]

答案 1 :(得分:1)

这是JAVA 8 lambdas和溪流。

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

/**
 * Created by joshua on 3/17/14.
 */
public class FindDuplicates {


  public static boolean isUnique(String x, List<String> list) {
    return 1 == list.stream().filter(s -> x.equals(s)).count();
  }

  public static void main(String[] args) {
    Map<String, Integer> seen = new HashMap<String, Integer>();
    List<String> list = Arrays.asList("a", "b", "c", "a", "b");
    Stream<String> finalStream = list.stream().map(x -> {
      int times = seen.getOrDefault(x, 0) + 1;
      seen.put(x, times);
      return x + times;
    }).map(x -> isUnique(x.substring(0,1), list)? x.substring(0,1) : x);

    System.out.println(Arrays.asList(finalStream.toArray()));
  }
}

答案 2 :(得分:0)

类似于PShemo的回答,但有点不同。

public class FindDuplicate {
public static final String ONE = "1";
public static void main(String args[]){
    String[] lists = {"a", "b", "c", "a", "b"};

    HashMap<String, PlaceHolder> dupCounts = new HashMap<>();
    for (int i = 0; i < lists.length; i++) {
        PlaceHolder placeHolder = dupCounts.get(lists[i]);
        if ( placeHolder != null){
            placeHolder.setCount(placeHolder.getCount() +1) ;
            lists[i] = lists[i].concat( placeHolder.toString());
        }else{
            placeHolder = new PlaceHolder();
            placeHolder.setCount(1);
            placeHolder.setFirstPosition(i);
            dupCounts.put(lists[i], placeHolder);
        }
    }

    for (Map.Entry<String, PlaceHolder> entry: dupCounts.entrySet()){
        if (entry.getValue().getCount() > 1){
            int position = entry.getValue().getFirstPosition();
            lists[position] = lists[position].concat(ONE);
        }
    }

    for (String string : lists) {
        System.out.println(string);
    }
}


 }

class PlaceHolder{
int count;
int firstPosition;
/**
 * @return the count
 */
public int getCount() {
    return count;
}
/**
 * @param count the count to set
 */
public void setCount(int count) {
    this.count = count;
}


/**
 * @return the firstPosition
 */
public int getFirstPosition() {
    return firstPosition;
}
/**
 * @param firstPosition the firstPosition to set
 */
public void setFirstPosition(int firstPosition) {
    this.firstPosition = firstPosition;
}
@Override
public String toString(){
    return count+"";
}

}

答案 3 :(得分:0)

我最初想的是这有点复杂。

我的第一个想法是简单地遍历List并使用Map<String, Integer>来计算每个字符的出现次数。在计数期间,您可以输出与运行计数连接的当前字符。这个代码很简单,但结果是:

{"a1", "b1", "c1", "a2", "b2"}

因为我们无法知道将再次看到哪些角色。

因此我们需要对数据进行一些预处理。首先,我们计算每个字符的出现次数:

final List<String> orig = Arrays.asList("a", "b", "c", "a", "b");
final Map<String, Integer> counts = new HashMap<>();
for (final String value : orig) {
    final Integer count = counts.get(value);
    if (count == null) {
        counts.put(value, 1);
    } else {
        counts.put(value, count + 1);
    }
}

计数现在包含:

{b=2, c=1, a=2}

新的,我们不能简单地向后循环原始数组并在这里减少计数,因为我们无法知道我们是否计数为1,因为我们之前输出了一些值,或者因为这是唯一的值

我的解决方案是复制count地图并将其称为seens。在这里,当我们生成输出时,我们会看到它们的值。

final List<String> result = new LinkedList<>();
final Map<String, Integer> seens = new HashMap<>(counts);
for (final String value : orig) {
    final Integer count = counts.get(value);
    if (count == 1) {
        result.add(value);
    } else {
        final Integer seen = seens.get(value);
        result.add(value + (count - seen + 1));
        seens.put(value, seen - 1);
    }
}
System.out.println(result);

所以我们再次遍历原始数组并为每个项目

  • 如果counts中的值为1,则只输出值
  • 如果counts中的值大于1,则从seens
  • 获取其值
  • 通过计算count - seen + 1计算我们看到的商品的数量,即项目总数减去(总数减去我们目前为止所见的数量)。
  • 输出value + number
  • 减少数量为seens