给出一个字符串列表/数组:如何删除列表中的类似命名字符串?
document
document (1)
document (2)
document (3)
mypdf (1)
mypdf
myspreadsheet (1)
myspreadsheet
myspreadsheet (2)
如何删除所有重复,但只保留了最高拷贝数?
结束的结果是:
document (3)
mypdf (1)
myspreadsheet (2)
给出一个字符串列表/数组:如何删除列表中的类似命名字符串?
document
document (1)
document (2)
document (3)
mypdf (1)
mypdf
myspreadsheet (1)
myspreadsheet
myspreadsheet (2)
如何删除所有重复,但只保留了最高拷贝数?
结束的结果是:
document (3)
mypdf (1)
myspreadsheet (2)
你把一个宽泛的问题,所以这里涉及的非特异性(但仍然)“完整”的答案:
换句话说,只需要这样一个简单的收据来解决这个问题;现在,只需要你的时间把这些伪代码指令转化为现实代码
对于记录:如果你的文件的布局真的如上所示,那么事情变得更容易 - 因为它似乎你的麻木ers正在增加。我的意思是:
X (1)
X (2)
X (3)
是很容易,
X (1)
X (3)
X (2)
至于你的情况来对待,似乎保存到假设最后 X(N)包含了最大的n个。这使得使用HashMap(如cainiaofei所建议的)一个很好的解决方案。
Set<T> mySet = new HashSet<T>(Arrays.asList(Your));
我发现,从计算器的其他用户,尝试,如果它的工作原理。好运:)
到目前为止有三个答案,都有相同的错误假设。注意'document'和'document(1)'是概念上的重复,而不是文字重复。需要进行一些处理和会计。 – bradimus
的替代解决方案
使用HashMap
关键是名称(例如文档文件的名称(1) 文件(2)文件(3)都是文件)
其可以通过此代码
str.substring(0,str.indexOf('(')).trim()
和值来实现是倍,目前的关键,最后遍历地图拿到钥匙那对应的值是最大,其结果是key(value-1)
您的解决方案只是将发现的最后**号码推入地图。如果格式与上面的格式非常相似,哪种方法可行?但如果不是这样?! – GhostCat
赞赏!只是寻找一个合乎逻辑的方法 –
@GhostCat对不起,我恐怕我不明白你的意思。至于OP的例子,我的地图将是<[document,4],[mypdf,2],[myspreadsheet,3]> –
我会建议你使用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
这是一个可行的方法,但是这只会工作如果版本号不超过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);
}
这是通过利用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);
}
让我们利用流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());
}
助手:
解挑选具有最高版本数解析函数:
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)]
我们实际上并不需要知道,如果元素包含不止一个空格或什么的。我们可以从最后开始,检查元素是否重复(查看是否有“)”)。
另外通过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;
}
有许多方法解决这个问题。你试过的任何代码?堆栈跟踪来检查错误? – Alfabravo
你所有的字符串都有这种格式吗?在名称中是否可以有空格,比如'my file'和'我的文件(23)'? – bradimus
是的,名称中也可以有空格 –