2016-11-17 61 views
1

给出一个字符串列表/数组:如何删除列表中的类似命名字符串?

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

如何删除所有重复,但只保留了最高拷贝数?

结束的结果是:

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

有许多方法解决这个问题。你试过的任何代码?堆栈跟踪来检查错误? – Alfabravo

+1

你所有的字符串都有这种格式吗?在名称中是否可以有空格,比如'my file'和'我的文件(23)'? – bradimus

+0

是的,名称中也可以有空格 –

回答

3

你把一个宽泛的问题,所以这里涉及的非特异性(但仍然)“完整”的答案:

  1. 遍历所有字符串来标识包含括号行。
  2. 换句话说:识别所有看起来像“X(n)”的字符串
  3. 然后,对于您找到的每个“不同”X,都可以重复列表;所以,你可以找到的“X”所有出现,X(1)“ ..等等
  4. 这样做将使您检测最大 N每个您的XES的。
  5. 推说” 。最大”,‘X(N)’,在结果列表

换句话说,只需要这样一个简单的收据来解决这个问题;现在,只需要你的时间把这些伪代码指令转化为现实代码

对于记录:如果你的文件的布局真的如上所示,那么事情变得更容易 - 因为它似乎你的麻木ers正在增加。我的意思是:

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

是很容易,

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

至于你的情况来对待,似乎保存到假设最后 X(N)包含了最大的n个。这使得使用HashMap(如cainiaofei所建议的)一个很好的解决方案。

+0

赞赏的逻辑援助。这是我需要的。 –

+0

欢迎您;-) – GhostCat

+0

请查看我的更新。 – GhostCat

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

我发现,从计算器的其他用户,尝试,如果它的工作原理。好运:)

+1

到目前为止有三个答案,都有相同的错误假设。注意'document'和'document(1)'是概念上的重复,而不是文字重复。需要进行一些处理和会计。 – bradimus

1

的替代解决方案


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

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

值来实现是倍,目前的关键,最后遍历地图拿到钥匙那对应的值是最大,其结果是key(value-1)

+0

您的解决方案只是将发现的最后**号码推入地图。如果格式与上面的格式非常相似,哪种方法可行?但如果不是这样?! – GhostCat

+0

赞赏!只是寻找一个合乎逻辑的方法 –

+0

@GhostCat对不起,我恐怕我不明白你的意思。至于OP的例子,我的地图将是<[document,4],[mypdf,2],[myspreadsheet,3]> –

0

我会建议你使用dictionnary:

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

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); 
    } 
0

这是通过利用Map的一个简单的解决方案。首先遍历列表,分割字符串,然后将其添加到地图中,名称作为关键字,以及作为值的pandant中的内容。并且为每个条目检查密钥是否已经存在。如果键存在,则比较该值,如果该值大于已存储的值,则将下一个条目添加到地图中。最后你循环浏览地图并获得你的列表。

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

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

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); 

} 
0

让我们利用流API来组我们的文件,并简单地通过版本号字符串排序挑选的最新版本。请记住,这些静态方法执行得不好,因为你没有给我们太多关于命名策略的信息,但这个想法应该清楚。

算法:

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()); 


} 

助手:

    同一字符串的
  1. 组修订一起
  2. 从每组

解挑选具有最高版本数解析函数:

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)]

0

我们实际上并不需要知道,如果元素包含不止一个空格或什么的。我们可以从最后开始,检查元素是否重复(查看是否有“)”)。

另外通过List一次作用中足以得到我们所需要的所有信息。假设,我提供其保存在一个Map最高出现值作为VALUE该地图将作为在给定的输入列表中的所有元素的解决方案。

之后,您可以创建结果List,并通过Map进行一次迭代。

public List<String> removeDuplicates(List<String> inputArray) {                
    Map<String, Integer> map = new HashMap<String, Integer>();                 
    List<String> result = new ArrayList<String>();                    

    int numberOfOcurences = 0;                         
    for (int i = 0; i < inputArray.size(); i++) {                    
     String element = inputArray.get(i);                     
     if (element.charAt(element.length() - 1) == ')') {                  
      numberOfOcurences = Character.getNumericValue(element.charAt(element.length() - 2));        
      element = element.substring(0, element.length() - 4);                
     } else {                            
      numberOfOcurences = 0;                        
     }                              
     if (map.isEmpty()) {                         
      map.put(element, numberOfOcurences);                    
     } else {                            
      if (null != map.get(element) && map.get(element) < numberOfOcurences) {           
       map.put(element, numberOfOcurences);                   
      } else if (null == map.get(element)) {                    
       map.put(element, numberOfOcurences);                   
      }                             
     }                              
    }                               
    for (String a : map.keySet()) {                       
     result.add(a + " (" + map.get(a)+ ")");                    
    }                               
    return result;                            
}