【问题标题】:Compare values between two list elements of same list比较同一列表的两个列表元素之间的值
【发布时间】:2015-08-17 21:35:06
【问题描述】:

我需要对以下类型的 List 中的值进行比较;

List<org.bson.Document>

数据是一个 Bson 文档,包含两个键:值对(名称和分数)。我需要遍历此列表并删除每个高尔夫球手的最低分数。所以,如果乔打了两场比赛,第一场比赛他得 72 分,第二场比赛他得 86 分,因为这是高尔夫,而 86 是两个得分中较低的,我需要从列表中删除有得分的元素86. 这将为每个高尔夫球手留下两者中较高的一个,然后让我只比较高分(较低的数值)。

使用 Java 1.8 的任何较新功能来执行此操作的最佳方法是什么,或者,我是否必须复制列表,然后将列表 A 中的元素 x 与列表 B 中的元素 x+1 进行比较(正确排序后)虽然名称相同?

【问题讨论】:

  • 是文档列表还是文档包含列表?
  • 您希望每个玩家只保留一个条目,还是每个玩家只保留最差的条目?或者换一种说法:您的示例是每个球员大约两个分数,是否总是如此,或者您可以将其重新表述为两个以上的分数?

标签: java list arraylist lambda comparison


【解决方案1】:

我不熟悉 bson,所以我尝试获取名称流,分数条目是这样的:

List<org.bson.Document> ldoc = new ArrayList<>();
Stream<Entry<String, Integer>> s
            = ldoc.stream()
            .flatMap(d -> d.entrySet().stream())
            .map(e -> new AbstractMap.SimpleImmutableEntry<String,Integer>(e.getKey(),((Integer)e.getValue())));

我直接从列表中创建了 Stream。

List<Entry<String, Integer>> l = new ArrayList<>();
    l.add(new AbstractMap.SimpleImmutableEntry<>("Joe", 72));
    l.add(new AbstractMap.SimpleImmutableEntry<>("Joe", 66));
    l.add(new AbstractMap.SimpleImmutableEntry<>("John", 73));
    l.add(new AbstractMap.SimpleImmutableEntry<>("John", 86));
    l.add(new AbstractMap.SimpleImmutableEntry<>("John", 99));

可以像这样在同一个流中分组和最小化:

Map<String, Optional<Integer>> m = l.stream()
            .collect(Collectors.groupingBy(e -> e.getKey(),
                            Collectors.mapping(e -> e.getValue(),
                                    Collectors.minBy((i1, i2) -> Integer.compare(i1, i2)))));
System.out.println("m = " + m);

这会产生输出:

m = {Joe=Optional[66], John=Optional[73]}

也就是说这是每个玩家名字最低分的地图。

要获得胜利者:

String winner = m.entrySet()
            .stream()
            .min((e1, e2) -> Integer.compare(e1.getValue().get(), e2.getValue().get()))
            .get().getKey();
System.out.println("winner = " + winner);

哪些打印:

winner = Joe

【讨论】:

    【解决方案2】:

    你必须使用列表吗? 尝试使用 hashMap,这样你可以检查你试图插入到 hashMap 中的玩家是否已经存在,如果是,你查看他的分数,如果更糟,你覆盖它。 之后,您应该得到得分最高的玩家的 hashMap。

    编辑: 我的坏..我没有正确阅读你的问题。您必须使用 bson.Document 数据类型。在这种情况下,您可以使用 treeSet 并定义一个自定义比较器,如果两个元素(玩家)具有相同的名称,它将返回 0(真)。然后您可以应用与原始答案中所写相同的逻辑。

    【讨论】:

      【解决方案3】:

      我并不真正了解 1.8,但我会简单地比较同一列表中的条目,而不创建第二个。我会这样做(使用伪方法,我不知道 bson):

      for (int i=0; i<List.length;i++) {
          int bestScore = List.getElementAt(i).getScore();
          int bestLocation = i;
          String currname = List.getElementAt(i).getName();
          for (int j=i+1;i<List.length;j++) {
              if (List.getElementAt(j).getName().equals(currname)) {
                  if (List.getElementAt(j).getScore()<bestScore) {
                      List.removeElementAt(bestLocation);
                      bestScore = List.getElementAt(j).getScore();
                      bestLocation = j;
                  } else {
                      List.removeElementAt(j);
                      j--;
                  }
              }
          }
      }
      

      ...或排序。认为你明白我的想法。您可能需要注意这可能导致的一些错误,但我希望我能帮助您解决这个问题。

      此外,由于 List.length 更改,这可能无法正常工作,但可以在删除某些内容时将其添加到代码中。

      【讨论】:

        【解决方案4】:

        我不确定你的问题。但是我从描述中了解到,我建议您使用 HasMap>。

        通过这种方式,您将能够对每个玩家的值进行排序,并且可以轻松删除最低分!!

        【讨论】:

          【解决方案5】:

          如果您知道一种遍历整个文档以获取分数的方法,则可以按升序对列表进行排序。排序后,您可以从列表中删除最后一个元素。有多种方法可以对列表进行排序。其中一些主要是冒泡排序和选择排序。

          您还可以查找最大值的索引并删除该元素。这种方法更容易也更有效。我还将为您提供此方法的伪代码。在代码中,列出你分配的Array list的名称。

          int max = list.get(0);
          index = 0;
          for(int i = 1; i < list.size(); i++)
          {
          if(list.get(i) > max)
          {
          max = list.get(i);
          index = i;
          }
          }
          list.remove(i);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-02-21
            • 2019-05-08
            • 2020-07-04
            • 2019-05-05
            • 1970-01-01
            • 2019-12-07
            相关资源
            最近更新 更多