考虑到以下代码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
public class FileNameSeq {
public static void main(String[] args) {
//List containing duplicate names
List<String> al = new ArrayList<String>(Arrays.asList("JAVA", "JAVA", "JAVA", "CPP", "JAVA", "CPP" ,"C"));
ArrayList<String> filenameList = new ArrayList<>();
for (int i = 0; al.size() > 0;) {
int freq = Collections.frequency(al, al.get(i));
String fileName = al.get(i);
filenameList.add(fileName.concat("-").concat("" + freq));
al.remove(i); /* removing the element */
}
System.out.println(filenameList);
}
}我已经开发了这段代码来生成序列,如果列表中存储了类似的名称,那么名称的第一次出现应该添加"-1",第二次出现"-2"等等,直到"-N",如果没有重复,那么名称应该保持不变。在运行程序时,我得到以下输出
[JAVA-4, JAVA-3, JAVA-2, CPP-2, JAVA-1, CPP-1, C-1]但是输出应该像
[JAVA-4, JAVA-3, JAVA-2, CPP-2, JAVA-1, CPP-1, C]C不应该附加"-1"。
我需要做哪些改变才能产生后来的输出?
发布于 2015-07-23 15:18:05
您必须测试您的集合中最初只有一次发生。
/**
* @param args
*/
public static void main(String[] args) {
//List containing duplicate names
List<String> al = new ArrayList<String>(Arrays.asList("JAVA", "JAVA", "JAVA", "CPP", "JAVA", "CPP" ,"C"));
ArrayList<String> filenameList = new ArrayList<String>();
//Creates a copy of the collection, which will remain unchanged
List<String> alCopy = new ArrayList<String>(al);
for (int i = 0; al.size() > 0;) {
String fileName = al.get(i);
int freq = Collections.frequency(al,fileName);
boolean toConcat = freq != 1;
if(!toConcat){
//checks if there was actually only one occurrence of filename
//or if it is only the last one
toConcat =( Collections.frequency(alCopy,fileName) != 1);
}
if(toConcat){
filenameList.add(fileName.concat("-").concat("" + freq));
//Why not filenameList.add(fileName + "-" + freq)); ??
} else {
filenameList.add(fileName);
}
al.remove(i); /* removing the element */
}
System.out.println(filenameList);
}请注意,此代码将生成您在问题中提到的输出。
JAVA-4,JAVA-3,JAVA-2,CPP-2,JAVA-1,CPP-1,C
如果您想要我建议的输出:
JAVA-1,JAVA-2,JAVA-3,CPP-1,JAVA-4,CPP-2,C
您可以使用以下代码使用映射来计数文件名的每一次出现。
/**
* @param args
*/
public static void main(String[] args) {
//List containing duplicate names
List<String> al = new ArrayList<String>(Arrays.asList("JAVA", "JAVA", "JAVA", "CPP", "JAVA", "CPP" ,"C"));
ArrayList<String> filenameList = new ArrayList<String>();
Map<String, Integer>counters = new HashMap<String, Integer>();
for(String fileName : al){
Integer count = counters.get(fileName);
boolean toConcat = true;
if(count == null){
//First occurence. Is it the only one?
count = 0;
if(Collections.frequency(al,fileName) == 1){
toConcat = false;
}
}
count += 1;
counters.put(fileName, count);
if(toConcat){
filenameList.add(fileName.concat("-").concat("" + count));
//Why not filenameList.add(fileName + "-" + count)); ??
} else {
filenameList.add(fileName);
}
}
System.out.println(filenameList);
}请注意,在本例中,我们不必修改原始集合,这要干净得多。
编辑
正如其他人在回答中提到的,第一个解决方案并不十分有效,因为Collection.frequency总是扫描整个集合。此外,在我看来,从原始集合中删除元素并不是很干净。
因此,我们可以使用类似于上面最后一个示例的代码来生成第一个输出([JAVA-4, JAVA-3, JAVA-2, CPP-2, JAVA-1, CPP-1, C-1])。它也基于计数器的映射,但在本例中,我们将每个文件名的出现次数减少,而不是从0开始增加计数器。
public static void main(String[] args) {
//List containing duplicate names
List<String> al = new ArrayList<String>(Arrays.asList("JAVA", "JAVA", "JAVA", "CPP", "JAVA", "CPP" ,"C"));
ArrayList<String> filenameList = new ArrayList<String>();
Map<String, Integer>counters = new HashMap<String, Integer>();
for(String fileName : al){
Integer count = counters.get(fileName);
boolean toConcat = true;
if(count == null){
//First occurrence.
//The number appended to the filename is the number of occurrences
count = Collections.frequency(al,fileName);
//Is it the only one? If so we won't append anything to the filename
//beware count is an Integer, not an int so '==' doesn't work
if(count.equals(1)){
toConcat = false;
}
} else {
//we can now decrease the counter
count -= 1;
}
counters.put(fileName, count);
if(toConcat){
filenameList.add(fileName.concat("-").concat("" + count));
//Why not filenameList.add(fileName + "-" + count)); ??
} else {
filenameList.add(fileName);
}
}
System.out.println(filenameList);
}发布于 2015-07-23 14:53:31
集合中的最后一个元素有一个频率,您可以使用条件从末尾删除它。
filenameList.add(fileName.concat(al.size() == 1?"":("-" + freq)));发布于 2015-07-23 15:06:51
Roman和Prerak的答案都很好,但并不完全符合预期的输出。他们的产出将是。。。
JAVA-4,JAVA-3,JAVA-2,CPP-2,,CPP,C
因为您要从源列表中删除,所以当您到达单个项目时,您无法判断该项目是否重复。您需要为每个项目保留某种类型的地图或状态。
我会做以下几点。。。(这是如果您真的想拥有“Java-1”/“CPP-1”项的话)
1)制作地图Map<String,Integer>
2)在地图中填充关键字为列表项(例如:“JAVA”、"CPP")和值是列表项的计数(例如,4表示"JAVA",2表示"CPP")。
3)遍历条目。如果值为== 1,则将键添加到输出列表中。如果计数> 1,则将ITEM + "-" + i for i = 1...count添加到输出列表中
这是一些psuedocode
List<String> output = new ArrayList<String>();
List<String> list = {"JAVA","JAVA","JAVA","CPP","JAVA","CPP", "C"};
Map<String, Integer> map = new HashMap<String, Integer>();
for(String item : list) {
if(map.contains(item)) {
map.put(item, map.get(item)+1);
} else {
map.put(item, 1);
}
}
for(Entry<String,Integer> entry : map.entrySet()) {
if(entry.value == 1) {
output.add(entry.key);
} else if(entry.value > 1) {
for(int i = 1; i <= entry.value; i++) {
output.add(entry.key + "-" + i);
}
}
}注-这应该输出正确的项目,但订单将不会被保留。
https://stackoverflow.com/questions/31590670
复制相似问题