How to combine list elements and find the price of largest combination

◇◆丶佛笑我妖孽 提交于 2019-12-10 11:27:49

问题


I have a class that holds details of a particular item like the following:

Detail.class

Long detailsId;
Integer price;
List<Long> stackableDetails;

/*getters and setters*/

Now, I have a sample dataset like the following:

    DetailId    Price    StackableDetails
------------------------------------------
    1011        4$       1012, 1014
    1012        6$       1011,1013
    1013        10$      1012
    1014        8$       1011

This data set maps to List sampleDetails. Now, based on the stackableDetails information, I have to combine the details and pick the combination having the max price from it.

For eg,
In the data set available, the possible combinations would be
1011,1012,1014 - 4+6+8 = 18$
1012,1011,1013 - 6+4+10 = 20$
1013,1012 - 10+6 = 16$
1014,1011 - 8+4 = 12$

Now the combination of details 1012,1011,1013 yields 20$, so I fetch this combination and add this in my result list. How can I achieve this in java8.

Any help appreciated. Thanks!


回答1:


Well, first it's a bit misleading. In your question you say pick the combination having the least price from it, but then later (and your comments) you actually provide the samples that yields the max result.

Assuming you need the max result, you could use this:

 long maxPrice = list
            .stream()
            .map(d -> Stream.concat(Stream.of(d.getDetailsId()), d.getStackableDetails().stream()))
            .map(s -> s.reduce(0L, (left, right) -> left +
                    list.stream()
                            .filter(dt -> dt.getDetailsId().equals(right))
                            .findAny()
                            .get()
                            .getPrice()))
            .max(Comparator.naturalOrder())
            .orElse(0L);

    System.out.println(maxPrice); // 20

EDIT

Well you want to compare by max price, but output set the make this price. The only thing I could come up with is to put them into a TreeMap, but that is not very readable IMHO. Also, there is the case when you have entries that collide - they have the same max price. This example simply takes the last one in encounter order.

  List<Long> highest = list
            .stream()
            .map(d -> Stream.concat(Stream.of(d.getDetailsId()), d.getStackableDetails().stream()).collect(Collectors.toList()))
            .collect(Collectors.toMap(s -> s.stream().reduce(0L,
                    (left, right) -> left + list.stream().filter(dt -> dt.getDetailsId().equals(right)).findAny().get().getPrice()),
                    s -> s.stream().collect(Collectors.toList()),
                    (left, right) -> right,
                    TreeMap::new))
            .lastEntry().getValue();

EDIT2

  Map<List<Long>, Long> map = list
            .stream()
            .map(d -> Stream.concat(Stream.of(d.getDetailsId()), d.getStackableDetails().stream()).collect(Collectors.toList()))
            .collect(Collectors.toMap(
                    s -> s.stream().collect(Collectors.toList()),
                    s -> s.stream().reduce(0L,
                            (left, right) -> left + list.stream().filter(dt -> dt.getDetailsId().equals(right)).findAny().get().getPrice()),
                    (left, right) -> right));



回答2:


Looking at Eugenes answer I thought that should work also a bit shorter... Here is another variant using flatMap and mapToDouble and the DoubleStream's sum and max:

double maxPrice = details.stream()
    .mapToDouble(detail -> Stream.concat(Stream.of(detail.getDetailsId()),
                                         detail.getStackableDetails().stream())
      .flatMap(detailId -> details.stream()
        .filter(candidateDetail -> detailId.equals(candidateDetail.getDetailsId())))
      .map(Detail::getPrice)
      .mapToDouble(value -> /* your transformation function */ (double) value)
      .sum()
    )
    .max()
    .orElse(0.0);

I wonder, why you might only sum up the details and its immediate stackable details. It sounds like a recursive problem to me, but on the other side, you probably know, what you need :-)

Regarding your other question: you may just want to replace the transformation step into the following:

.mapToDouble(Double::parseDouble)

Note that you can exchange double/mapToDouble, etc. to whatever suits you the most. sum() however is only available to the three primitive streams: IntStream, LongStream and DoubleStream.



来源:https://stackoverflow.com/questions/43734400/how-to-combine-list-elements-and-find-the-price-of-largest-combination

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