在遍历列表时计算并删除列表中的相似元素

Count and remove similar elements in a list while iterating through it

我在网站中使用了很多参考资料来构建我的程序,但我现在有点卡住了。我认为使用 iterator 就可以了。可悲的是,即使我经历了带有迭代器的问题,我也无法正确使用它来在我的代码中实现它。

我想, 1.删​​除列表中找到的相似元素fname 2. 将 fname 中找到的每个元素的那个计数添加到 counter

请帮助我使用迭代器或任何其他方法完成上述操作。以下是我的代码,

List<String> fname = new ArrayList<>(Arrays.asList(fullname.split(""))); //Assigning the string to a list//

    int count = 1;
    ArrayList<Integer> counter = new ArrayList<>();
    List<String> holder = new ArrayList<>();

    for(int element=0; element<=fname.size; element++)
    {
        for(int run=(element+1); run<=fname.size; run++)
        {
            if((fname.get(element)).equals(fname.get(run)))
            {
                count++;
                holder.add(fname.get(run));
            }

            counter.add(count);                    
        }

        holder.add(fname.get(element));
        fname.removeAll(holder);
    }

    System.out.println(fname);
    System.out.println(counter);

谢谢。

您可以尝试这样的操作:

Set<String> mySet = new HashSet<>();
mySet.addAll( fname ); // Now you have unique values

for(String s : mySet) {
    count = 0;
    for(String x : fname) {
        if( s.equals(x) ) { count++; }
    }
    counter.add( count );
}

这样我们没有特定的顺序。但我希望它能有所帮助。

在Java8中,有一行:

List<Integer> result = fname
    .stream()
    .collect(Collectors.groupingBy(s -> s))
    .entrySet()
    .stream()
    .map(e -> e.getValue().size())
    .collect(Collectors.toList());

我认为您在这里不需要迭代器。但是,您可以使用许多其他可能的解决方案,例如递归。不过,我刚刚修改了您的代码如下:

    final List<String> fname = new ArrayList<String>(Arrays.asList(fullname.split("")));
    // defining a list that will hold the unique elements.
    final List<String> resultList = new ArrayList<>();
    // defining a list that will hold the number of replication for every item in the fname list; the order here is same to the order in resultList
    final ArrayList<Integer> counter = new ArrayList<>();

    for (int element = 0; element < fname.size(); element++) {
        int count = 1;
        for (int run = (element + 1); run < fname.size(); run++) {
            if ((fname.get(element)).equals(fname.get(run))) {
                count++;
                // we remove the element that has been already counted and return the index one step back to start counting over.
                fname.remove(run--);
            }
        }
        // we add the element to the resulted list and counter of that element
        counter.add(count);
        resultList.add(fname.get(element));
    }
    // here we print out both lists.
    System.out.println(resultList);
    System.out.println(counter);

假设String fullname = "StringOfSomeStaff";输出如下:

[S, t, r, i, n, g, O, f, o, m, e, a]
[3, 2, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1]

根据你的问题,你基本上想:

1.从给定的字符串列表中消除重复项

您可以简单地将您的列表转换为 HashSet(它不允许重复),然后将其转换回列表(如果您希望最终结果是一个列表,那么您可以使用它...)

2。计算列表中出现的所有唯一单词 最快的编码是使用 Java 8 Streams(从这里借用的代码:How to count the number of occurrences of an element in a List

完整代码

public static void main(String[] args) {
    String fullname = "a b c d a b c"; //something
    List<String> fname = new ArrayList<>(Arrays.asList(fullname.split(" ")));

    // Convert input to Set, and then back to List (your program output)
    Set<String> uniqueNames = new HashSet<>(fname);
    List<String> uniqueNamesInList = new ArrayList<>(uniqueNames);
    System.out.println(uniqueNamesInList);

    // Collects (reduces) your list
    Map<String, Long> counts = fname.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    System.out.println(counts);
}

我使用 LinkedHashMap 来保持元素的顺序。我正在使用的 for 循环也隐式使用了 Iterator。代码示例使用 Map.merge 方法,自 Java 8.

起可用
    List<String> fname = new ArrayList<>(Arrays.asList(fullname.split("")));
    /*
        Create Map which will contain pairs kay=values
        (in this case key is a name and value is the counter).
        Here we are using LinkedHashMap (instead of common HashMap)
        to preserve order in which name occurs first time in the list.
    */
    Map<String, Integer> countByName = new LinkedHashMap<>();
    for (String name : fname) {
        /*
             'merge' method put the key into the map (first parameter 'name').
             Second parameter is a value which we that to associate with the key
             Last (3rd) parameter is a function which will merge two values
             (new and ald) if map already contains this key
         */
        countByName.merge(name, 1, Integer::sum);
    }
    System.out.println(fname);                  // original list [a, d, e, a, a, f, t, d]
    System.out.println(countByName.values());   // counts [3, 2, 1, 1, 1]
    System.out.println(countByName.keySet());   // unique names [a, d, e, f, t]

同样可以使用 Stream API 但如果您不熟悉 Streams 可能很难理解。

    Map<String, Long> countByName = fname.stream()
            .collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()));