如何删除列表中类似的命名字符串?

时间:2016-11-17 14:04:04

标签: java arrays list

给定一个字符串列表/数组:

document
document (1)
document (2)
document (3)
mypdf (1)
mypdf
myspreadsheet (1)
myspreadsheet
myspreadsheet (2)

如何删除所有重复项但仅保留最高副本号?

结束结果:

document (3)
mypdf (1)
myspreadsheet (2)

8 个答案:

答案 0 :(得分:3)

你提出了一个广泛的问题,所以这里有一个非特定的(但仍然是)"完整的"回答:

  1. 遍历所有字符串以识别包含大括号的所有行。
  2. 换句话说:识别所有看起来像" X(n)"
  3. 的字符串
  4. 然后,对于每个"不同的"你找到的X,你可以再次迭代列表;这样你就可以找到所有出现的" X",X(1)",..等等
  5. 这样做可以让您检测每个Xes的最大 n。
  6. 推动"最大" " X(n)"进入结果列表。
  7. 换句话说:它只需要这么简单的收据来解决这个问题;现在只需要花时间将这些伪代码指令转换为实际代码。

    对于记录:如果您的文件布局真的如上所示,那么事情会变得容易一些 - 因为您的数字似乎正在增加。我的意思是:

    X (1)
    X (2)
    X (3)
    

    更容易治疗
    X (1)
    X (3)
    X (2)
    

    在你的情况下,假设最后 X(n)包含最大的n,似乎可以节省。这使得使用HashMap(由cainiaofei建议)是一个很好的解决方案。

答案 1 :(得分:1)

替代解决方案

使用HashMap密钥是名称(例如文档文档的名称(1) 文件(2)文件(3)都是文件

  

可以通过此代码str.substring(0,str.indexOf('(')).trim()

实现

并且是密钥存在的时间,最后遍历地图获取对应值为max 的密钥,结果为key(value-1) < / p>

答案 2 :(得分:0)

我建议你使用词典:

Map<String, Integer> dict = new HashMap<>();
for (String s : listOfInput){
    String name = s.split(" ")[0];
    String version = s.split(" ")[1].charAt(1);
    if(dict.get(name)!=null){
        if (Integer.parseInt(version) < dict.get(name)){
            continue;
        }
    }
    dict.put(name, version); 
}

数据将在字典的末尾:

键|值

文件| 3

mypdf | 1

myspreadsheet | 2

答案 3 :(得分:0)

这是一种可能的方法,但只有在版本号不超过9 时才会使用

1)按相反顺序对列表进行排序,以便最新版本首先出现

(*)排序基于字母顺序,除非您的版本号超过一位数,否则您应该非常精细。例如10,出现在9之前,按字母排序。

您的列表将变为:

myspreadsheet (2)
myspreadsheet (1)
myspreadsheet
mypdf (1)
mypdf
document (3)
document (2)
document (1)
document

2)迭代列表,只保留给定文档的第一次出现(即最近感谢反向排序)

3)如果您愿意,可以将剩余列表排序为更自然的顺序

    List<String> documents = new ArrayList<String>();

    documents.add("document");
    documents.add("document (1)");
    documents.add("document (2)");
    documents.add("document (3)");
    documents.add("mypdf (1)");
    documents.add("mypdf");
    documents.add("myspreadsheet (1)");
    documents.add("myspreadsheet");
    documents.add("myspreadsheet (2)");

    // 1) Sort in reverse order, so that the most recent document version appears first
    Collections.sort(documents, Collections.reverseOrder());

    String lastDocumentName = "";

    ListIterator<String> iter = documents.listIterator();

    // 2)
    while (iter.hasNext()) {

        String document = iter.next();

        // Store the first part of the String , i.e the document name (without version)
        String firstPart = document.split("\\s+")[0];

        // Check if this document is a version of the last checked document
        // If it is the case, this version is anterior, remove it from the list
        if (lastDocumentName.equals(firstPart)) {

            iter.remove();

        }

        // Store this document's name as the last one checked
        lastDocumentName = firstPart;

    }

    // 3) Sort back to natural order
    Collections.sort(documents);

    for (String doc : documents) {

        System.out.println(doc);
    }

答案 4 :(得分:0)

这是一个使用Map的简单解决方案。首先,您遍历列表,拆分字符串,然后将其添加到地图中,并将名称作为键,以及作为值在paranthesis中的内容。并为每个条目检查密钥是否已存在。如果密钥存在,则比较该值,如果该值大于已存储的值,则将下一个条目添加到地图中。最后,您将遍历地图并获取列表。

这可能适用于任何类型的输入。我想......

当然,这可以比这更好。如果有人有任何建议,请随时分享。

public static void main(String[] args) {
    List<String> list = Arrays.asList("document", "document (1)", "document (2)", "document (3)", "mypdf (1)", "mypdf", "myspreadsheet (1)",
            "myspreadsheet", "myspreadsheet (2)");

    Map<String, Integer> counterMap = new HashMap<>();
    List<String> newList = new ArrayList<>();

    for (String item : list) {
        if (item.indexOf(')') != -1) {
            String namePart = item.substring(0, item.indexOf('(')).trim();
            Integer numberPart = Integer.parseInt(item.substring(item.indexOf('(') + 1, item.indexOf(')')));

            Integer existingValue = counterMap.get(namePart);
            if (existingValue != null) {
                if (numberPart > existingValue) {
                    counterMap.put(namePart, numberPart);
                }
            } else {
                counterMap.put(namePart, numberPart);
            }
        } else {
            newList.add(item);
        }

    }

    Iterator<Entry<String, Integer>> iterator = counterMap.entrySet().iterator();
    while (iterator.hasNext()) {
        Entry<String, Integer> next = iterator.next();
        String key = next.getKey();
        Integer value = next.getValue();
        if (newList.contains(key)) {
            newList.remove(key);
        }

        newList.add(key + " (" + value + ")");
    }

    System.out.println(newList);

}

答案 5 :(得分:0)

让我们利用Stream API对我们的文档进行分组,并通过按版本号对字符串进行排序来选择最新版本。请记住,那些静态方法实施得很差,因为你没有给我们太多关于命名策略的信息,但这个想法应该是明确的。

算法:

  1. 同一个字符串的组修订
  2. 从每个组中选择具有最高版本的号码
  3. <强>解决方案:

        Map<String, List<String>> grouped = input.stream()
          .collect(Collectors.groupingBy(preprocessedString(), Collectors.toList()));
    
        List<String> finalResult = grouped.entrySet().stream()
          .map(e -> e.getValue().stream()
            .max(Comparator.comparing(revisionNumber())).get()) //at this point we have at least one element
          .collect(Collectors.toList());
    
    
    }
    

    帮助器解析函数:

    private static Function<String, Integer> revisionNumber() {
        return s -> s.contains("(") ? Integer.valueOf(s.substring(s.indexOf('(') + 1, s.indexOf(')'))) : 0;
    }
    
    private static Function<String, String> preprocessedString() {
        return s -> s.contains("(") ? s.substring(0, s.lastIndexOf("(")).trim() : s.trim();
    }
    

    <强>输入:

    List<String> input = Arrays.asList(
          "document",
          "document (1)",
          "document (2)",
          "document (3)",
          "mypdf (1)",
          "mypdf",
          "myspreadsheet (12)",
          "myspreadsheet",
          "myspreadsheet (2)",
          "single");
    

    <强>结果[single, myspreadsheet (12), document (3), mypdf (1)]

答案 6 :(得分:0)

我们实际上不需要知道元素是否包含多个空格或其他内容。我们可以从最后开始,检查元素是否重复(看看是否有“)”。

通过document.getElementByID进行一次整理就足以获得我们需要的所有信息。假设,我提供了一个解决方案,它将最高外观值保存为document.getElementById中的 VALUE ,该地图将具有 KEYs 给定输入中的所有元素列表。

之后,您可以通过List再次创建结果Map

List

答案 7 :(得分:-5)

Set<T> mySet = new HashSet<T>(Arrays.asList(Your));

我从stackoverflow的另一个用户发现,尝试它是否有效。祝你好运:)