首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将序列添加到存储在列表中的名称(如果重复)

如何将序列添加到存储在列表中的名称(如果重复)
EN

Stack Overflow用户
提问于 2015-07-23 14:42:24
回答 9查看 1.3K关注 0票数 1

考虑到以下代码:

代码语言:javascript
复制
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",如果没有重复,那么名称应该保持不变。在运行程序时,我得到以下输出

代码语言:javascript
复制
[JAVA-4, JAVA-3, JAVA-2, CPP-2, JAVA-1, CPP-1, C-1]

但是输出应该像

代码语言:javascript
复制
[JAVA-4, JAVA-3, JAVA-2, CPP-2, JAVA-1, CPP-1, C]

C不应该附加"-1"

我需要做哪些改变才能产生后来的输出?

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2015-07-23 15:18:05

您必须测试您的集合中最初只有一次发生。

代码语言:javascript
复制
/**
 * @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

您可以使用以下代码使用映射来计数文件名的每一次出现。

代码语言:javascript
复制
/**
 * @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开始增加计数器。

代码语言:javascript
复制
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);
}
票数 1
EN

Stack Overflow用户

发布于 2015-07-23 14:53:31

集合中的最后一个元素有一个频率,您可以使用条件从末尾删除它。

代码语言:javascript
复制
filenameList.add(fileName.concat(al.size() == 1?"":("-" + freq)));
票数 0
EN

Stack Overflow用户

发布于 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

代码语言:javascript
复制
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);
       }
    }
}

注-这应该输出正确的项目,但订单将不会被保留。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31590670

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档