Java 查找多个列表中的元素数并合并;是否删除if/else复合体?

Java 查找多个列表中的元素数并合并;是否删除if/else复合体?,java,list,Java,List,我有一份清单: List<List<String>> someList = new List<List<>>(); 我正试图设计一种方法,通过组合上面的一些嵌套列表来创建一个特定大小(1-5个元素)的新列表。我可以做如下操作(在本例中,有三个元素): getThree()方法正在创建一个由someList子列表中的元素组成的新列表。它不能拆分子列表(即,它不能从包含2个元素的子列表中提取1个元素),它正在合并整个子列表。因为您声明组合列表的优先级

我有一份清单:

List<List<String>> someList = new List<List<>>();
我正试图设计一种方法,通过组合上面的一些嵌套列表来创建一个特定大小(1-5个元素)的新列表。我可以做如下操作(在本例中,有三个元素):


getThree()
方法正在创建一个由
someList
子列表中的元素组成的新列表。它不能拆分子列表(即,它不能从包含2个元素的子列表中提取1个元素),它正在合并整个子列表。

因为您声明组合列表的优先级是从左到右。O(N^2)循环足以处理组合子列表小于或等于所需数量的情况

public static void main(String[] args) throws Exception {
    List<List<String>> someList = new ArrayList() {{
       add(new ArrayList() {{
           add("a1");
           add("a2");
       }});
       add(new ArrayList() {{
           add("b1");
       }});
       add(new ArrayList() {{
           add("c1");
           add("c2");
           add("c3");
       }});
       add(new ArrayList() {{
           add("d1");
       }});
    }};

    combine(someList, 4);

    for(List<String> subList : someList) {
        System.out.println(subList);
    }
}

private static void combine(List<List<String>> someList, int combineAmount) {
    for (int i = 0; i < someList.size(); i++) {
        // Check if the current list already equals or exceeds the combineAmount
        if (someList.get(i).size() >= combineAmount) {
            continue;
        }

        // Add sublists to the current sublists until the size of the current
        // sublist equals or exceeds the combineAmount
        for (int j = i + 1; j < someList.size(); j++) {
            if (someList.get(i).size() + someList.get(j).size() > combineAmount) {
                continue;
            }
            someList.get(i).addAll(someList.get(j));
            someList.remove(j);
            j--;

            // Don't bother checking other sublists if the newly 
            // combined sublists equals or exceeds the combineAmount
            if (someList.get(i).size() >= combineAmount) {
                break;
            }
        }
    }
}
结果(组合计数=2):

结果(组合计数=6):


如果您打算从连续列表中继续收集,直到获得5个元素,请继续添加,然后在列表已满时中断:

public static List<String> fill(List<List<String>> sources, int size) {
    List<String> list = new ArrayList<>();
    for (List<String> source : sources) 
        if (source.size() <= size - list.size()) 
            list.addAll(source);
    return list;
}

在java 8中,非常简洁:

public static List<String> fill(List<List<String>> sources, int size) {
    return sources.stream().reduce(new ArrayList<>(), 
      (a, b) -> {if (b.size() <= a.size() - size) a.addAll(b); return a;});
}
公共静态列表填充(列表源,整数大小){
返回sources.stream().reduce(新的ArrayList(),
(a,b)->{if(b.size()b.size()-a.size())
.reduce(新的ArrayList(),(a,b)->

{if(b.size()据我所知,您希望将列表列表合并为总共5个索引。执行此操作时,您希望它首先对左侧进行优先级排序

以下是我创建的一个方法。我知道您不想要一个具体的示例,但我认为示例将帮助您理解并帮助其他也有此问题的人:

private static List<String> getListOf(List<List<String>> someList, int size) {
    List<List<String>> combine = new ArrayList<List<String>>();
    List<List<String>> combinePrev = new ArrayList<List<String>>();
    int value = 0;
    int indexCloseValue = 0;
    int indexClose;
    for(int i = 0; i < someList.size(); i++){//Loops through the lists
        value = someList.get(i).size();
        boolean[] indexAdded = new boolean[someList.size()];//Used to make sure to not add duplicates
        indexAdded[i] = true;
        combine.add(someList.get(i));//add current loop to the combine list.
        do{//A loop to try to add values other than the one of index i to equal size.  This loops multiple times because it may take more than two to equal size.
            indexCloseValue = 0;
            indexClose = -1;
            for(int j = 0; j < someList.size(); j++){
                if(!indexAdded[j]){
                    int listSize = someList.get(j).size();
                    if(value + listSize > indexCloseValue && value + listSize <= size){
                        indexCloseValue = listSize;
                        indexClose = j;
                    }
                }
            }
            if(indexClose == -1){
                break;
            }else{
                combine.add(someList.get(indexClose));
                value+=indexCloseValue;
                indexAdded[indexClose] = true;
            }
        }while(value + indexCloseValue < size);
        int added = 0;
        for(List<String> str : combine){//Check size of combine list
            added+=str.size();
        }
        int addedPrev = 0;
        for(List<String> str : combinePrev){//Check size of combinePrev list
            addedPrev+=str.size();
        }
        if(added > addedPrev && added <= size){
            combinePrev = new ArrayList<List<String>>(combine);//Set combinePrev to combine if it is larger but less than size
        }
        combine = new ArrayList<List<String>>();//Reset combine
    }

    List<String> returnList = new ArrayList<String>();
    for(List<String> list : combinePrev){//converts double list to a single list of strings at length "size".
        for(String str : list){
            returnList.add(str);
        }
    }
    return returnList;      
}
private静态列表getListOf(List someList,int size){
List combine=new ArrayList();
List combinePrev=new ArrayList();
int值=0;
int indexCloseValue=0;
int indexClose;
for(int i=0;i如果(value+listSize>indexCloseValue&&value+listSize addedPrev&&added)您是否正在尝试将列表列表转换为单个列表?我理解正确吗?我必须走大约一个小时,如果这个问题没有得到回答,那么我想我有一个答案给您。组合哪些列表以及项目的顺序是否重要?Sa如果您有大小为
{1,3,2,4,1}
myList
,并且您想要一个大小为
size=5
的结果列表,那么以下所有组合都被认为是解决方案吗?
{1+3+1}
{3+2}
{4+1}
@Kobit,可以组合任意数量的列表,但最左边的列表优先。在您的示例中,它将是
{1+3+1}
。类似于“如果它可以使用子列表1,就使用它;如果它不能使用子列表2,就使用它;…”。是不是你想继续从连续列表中添加元素,直到你有5个?@Shar1er80我没有注意到。事实上,考虑到这一点,代码变得简单多了。你认为编辑后的代码符合OP现在的要求吗?我更喜欢你的解决方案,因为我认为我更了解OP的意图。我只是不明白它的目的每次调用都返回相同的结果。我认为合并是永久性的,而不是临时性的,因为您可能会遇到这样的情况,即您永远不会看到子列表是返回结果的一部分。例如,在OP的示例列表{4,1,3,1}中,每次调用潜在的getOne()将始终导致索引1处的子列表,而索引3处的子列表将永远不会返回。
[a1, a2, b1, d1]
[c1, c2, c3]
[a1, a2]
[b1, d1]
[c1, c2, c3]
[a1, a2, b1, c1, c2, c3]
[d1]
public static List<String> fill(List<List<String>> sources, int size) {
    List<String> list = new ArrayList<>();
    for (List<String> source : sources) 
        if (source.size() <= size - list.size()) 
            list.addAll(source);
    return list;
}
Collections.sort(sources, (a, b) -> b.size() - a.size());
public static List<String> fill(List<List<String>> sources, int size) {
    return sources.stream().reduce(new ArrayList<>(), 
      (a, b) -> {if (b.size() <= a.size() - size) a.addAll(b); return a;});
}
public static List<String> fill(List<List<String>> sources, int size) {
    return sources.stream()
        .sorted((a,b) -> b.size() - a.size())
        .reduce(new ArrayList<>(), (a, b) -> 
            {if (b.size() <= a.size() - size) a.addAll(b); return a;});
}
private static List<String> getListOf(List<List<String>> someList, int size) {
    List<List<String>> combine = new ArrayList<List<String>>();
    List<List<String>> combinePrev = new ArrayList<List<String>>();
    int value = 0;
    int indexCloseValue = 0;
    int indexClose;
    for(int i = 0; i < someList.size(); i++){//Loops through the lists
        value = someList.get(i).size();
        boolean[] indexAdded = new boolean[someList.size()];//Used to make sure to not add duplicates
        indexAdded[i] = true;
        combine.add(someList.get(i));//add current loop to the combine list.
        do{//A loop to try to add values other than the one of index i to equal size.  This loops multiple times because it may take more than two to equal size.
            indexCloseValue = 0;
            indexClose = -1;
            for(int j = 0; j < someList.size(); j++){
                if(!indexAdded[j]){
                    int listSize = someList.get(j).size();
                    if(value + listSize > indexCloseValue && value + listSize <= size){
                        indexCloseValue = listSize;
                        indexClose = j;
                    }
                }
            }
            if(indexClose == -1){
                break;
            }else{
                combine.add(someList.get(indexClose));
                value+=indexCloseValue;
                indexAdded[indexClose] = true;
            }
        }while(value + indexCloseValue < size);
        int added = 0;
        for(List<String> str : combine){//Check size of combine list
            added+=str.size();
        }
        int addedPrev = 0;
        for(List<String> str : combinePrev){//Check size of combinePrev list
            addedPrev+=str.size();
        }
        if(added > addedPrev && added <= size){
            combinePrev = new ArrayList<List<String>>(combine);//Set combinePrev to combine if it is larger but less than size
        }
        combine = new ArrayList<List<String>>();//Reset combine
    }

    List<String> returnList = new ArrayList<String>();
    for(List<String> list : combinePrev){//converts double list to a single list of strings at length "size".
        for(String str : list){
            returnList.add(str);
        }
    }
    return returnList;      
}