Generate List with Combination of Subset of List, Java

廉价感情. 提交于 2019-12-02 14:44:39

问题


This question is to be implemented in Java.

I have a class named Competitor, with Type, Name and Power.

public class Competitor {
  private final int type;
  private final String name;
  private final int power;

  public Competitor(int type, String name, int power) {
    this.type = type;
    this.name = name;
    this.power = power;
  }

  public int getType() {
    return type;
  }

  public String getName() {
    return name;
  }

  public int getPower() {
    return power;
  }

  @Override
  public String toString() {
    return "Competitor{" + "type=" + type + ", name=" + name + ", power=" + power + '}';
  }

}

Now, I want to do a game, with ONE competitor by type, the numbers of type can be 60 (3D arrays or nested for is not a solution for me).

I want to generate all posible combination of sub Set (classified by type) of this List.

public class Game {
  public static void main(String... args) {
    List<Competitor> listCompetitors = new ArrayList<>();
    listCompetitors.add(new Competitor(1, "Cat 00", 93));
    listCompetitors.add(new Competitor(1, "Cat 10", 11));
    listCompetitors.add(new Competitor(1, "Cat 23", 20));

    listCompetitors.add(new Competitor(2, "Dog 61", 54));
    listCompetitors.add(new Competitor(2, "Dog 18", 40));
    listCompetitors.add(new Competitor(2, "Dog 45", 71));
    listCompetitors.add(new Competitor(2, "Dog 30", 68));

    listCompetitors.add(new Competitor(3, "Pig 90", 90));
    listCompetitors.add(new Competitor(3, "Pig 78", 32));

    listCompetitors.add(new Competitor(4, "Cow 99", 90));

    // The type is NOT fixed number (is variable from 1 to 60)
  }
}

How is possible generate the combination like...

new Competitor(1, "Cat 00", 93)
new Competitor(2, "Dog 61", 54)
new Competitor(3, "Pig 90", 90)
new Competitor(4, "Cow 99", 90)

Another combination

new Competitor(1, "Cat 00", 93)
new Competitor(2, "Dog 61", 54)
new Competitor(3, "Pig 78", 32)
new Competitor(4, "Cow 99", 90)

...

The last combination

new Competitor(1, "Cat 23", 20)
new Competitor(2, "Dog 30", 68)
new Competitor(3, "Pig 78", 32)
new Competitor(4, "Cow 99", 90)

How generate sublist like proposed before?

I also raise the bet.

Taking in account the power parameter. What is are the List<Competitor> the worse(minimum sum of power) and best (maximum sum of parameter) performance?


回答1:


First, group all elements by type, to get the lists to combine.

Map<Integer, List<Competitor>> map
    = listCompetitors.stream().collect(Collectors.groupingBy(Competitor::getType));

Then, to build the Cartesian Product, we need a helper method to create a new List out of an existing List and an additional element. Unfortunately, there’s no built-in method for that (but you might find such operations in 3rd party libraries though)

static <T> List<T> listWith(List<T> list, T t) {
    List<T> result = new ArrayList<>(list.size() + 1);
    result.addAll(list);
    result.add(t);
    return result;
}

With that, we can construct a Stream and collect it into a result List:

Stream<List<Competitor>> stream = Stream.of(Collections.emptyList());
for(List<Competitor> next: map.values())
    stream = stream.flatMap(list -> next.stream().map(c -> listWith(list, c)));

List<List<Competitor>> listOfListCompetitor = stream.collect(Collectors.toList());

Each flatMap step will combine the stream with another dimension.

The collection operation of listWith could also be done with another stream operation, e.g.

Stream<List<Competitor>> stream = Stream.of(Collections.emptyList());
for(List<Competitor> next: map.values())
    stream = stream.flatMap(list -> next.stream()
        .map(c -> Stream.concat(list.stream(), Stream.of(c)).collect(Collectors.toList())));

List<List<Competitor>> listOfListCompetitor = stream.collect(Collectors.toList());

but that’s not as intuitive, imho.




回答2:


I believe solve the question

public class Game {

  public static void main(String... args) {
    List<Competitor> listCompetitors = new ArrayList<>();

    listCompetitors.add(new Competitor(1, "Cat 00", 93));
    listCompetitors.add(new Competitor(1, "Cat 10", 11));
    listCompetitors.add(new Competitor(1, "Cat 23", 20));

    listCompetitors.add(new Competitor(2, "Dog 61", 54));
    listCompetitors.add(new Competitor(2, "Dog 18", 40));
    listCompetitors.add(new Competitor(2, "Dog 45", 71));
    listCompetitors.add(new Competitor(2, "Dog 30", 68));

    listCompetitors.add(new Competitor(3, "Pig 90", 90));
    listCompetitors.add(new Competitor(3, "Pig 78", 32));

    listCompetitors.add(new Competitor(4, "Cow 99", 90));

    List<Integer> typeList = new ArrayList<>(listCompetitors.stream()
        .map(Competitor::getType)
        .collect(Collectors.toSet()));
    int sizeLimit = typeList.size();

    List<List<Competitor>> listOfListCompetitor = new ArrayList<>();
    getListCompetitorCombination(new ArrayList<>(), listCompetitors, sizeLimit, listOfListCompetitor);

    listOfListCompetitor.stream().forEach(listCompetitor -> {
      System.out.println("");
      listCompetitor.stream().sorted(Comparator.comparing(Competitor::getType)).forEach(System.out::print);
    });
    System.out.println();

  }

  public static List<Competitor> getListCompetitorCombination(List<Competitor> processed, List<Competitor> sublistCompetitor, int sizeLimit, List<List<Competitor>> outCompetitor) {
    List<Competitor> listCompetitorCombination = new ArrayList<>();

    /*
    List<Integer> typeList = new ArrayList<>(sublistCompetitor.stream()
        .map(Competitor::getType)
        .collect(Collectors.toSet()));
    */
    int type = sublistCompetitor.get(0).getType();//typeList.stream().findFirst().orElse(0);

    List<Competitor> listCompetitorsIncludeType = sublistCompetitor
        .stream()
        .filter(competitor -> competitor.getType() == type)
        .collect(Collectors.toList());

    List<Competitor> listCompetitorsExcludeType = sublistCompetitor
        .stream()
        .filter(competitor -> competitor.getType() != type)
        .collect(Collectors.toList());

    listCompetitorsIncludeType.stream().forEach(
        competitor
        -> {

      List<Competitor> newProcessed = new ArrayList<>(processed);
      newProcessed.add(0, competitor);
      if (sizeLimit == newProcessed.size()) {
        outCompetitor.add(newProcessed);
      } else {
        getListCompetitorCombination(newProcessed, listCompetitorsExcludeType, sizeLimit, outCompetitor);
      }
    });
    return listCompetitorCombination;
  }

}

My output

    debug:

    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    BUILD SUCCESSFUL (total time: 1 second)

Now, Can someone propose another optimized solution?



来源:https://stackoverflow.com/questions/56095738/generate-list-with-combination-of-subset-of-list-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!