代码之家  ›  专栏  ›  技术社区  ›  JNMN

如何将一个列表划分为较小的列表

  •  0
  • JNMN  · 技术社区  · 8 年前

    我目前正在做一个项目,我有以下几点

        for (String x : listOne) {
            for (String y : listOne) {
                for (String z : listTwo) {
                    if (x.noun1.equal(z.noun1) && y.noun2.equals(z.noun2)) {
                        doSomething();
                    }
                }
            }
        }
    

    其中listOne和listwo只是 ArrayList<String> s、 两者 ArrayList s保持动词:名词:名词对,其中我们在索引0处有一个动词,在索引1处有一个名词,在索引2处有一个名词(依此类推)。

    这本质上只是一种暴力搜索算法。 为了优化搜索过程,我想创建一个较小的x的三元组列表,其中x的名词1与z相同,y的三元组列表中y的名词2与z相同。我对java中的lambda表达式一无所知,但经过一些研究,我确信有一种方法可以在java中使用lambda实现这一点。

    如果您能帮我做这件事,或者给我一些有用的文章,我们将不胜感激。

    编辑:下面是一个示例

    ArrayList<String> al1 = "IsA","Car","Vehicle","IsA","house","building"..
    ArrayList<String> al2 = "IsA","house","home"..
    

    自从 al1 索引4处的名词1等于 al2 索引1处的名词1。我们将返回一个新的ArrayList或地图,其中包含“IsA”、“house”和“building”。

    3 回复  |  直到 8 年前
        1
  •  1
  •   maaartinus    8 年前

    你应该把上一个问题联系起来,否则就不可能理解你想要什么。IIUYC你要求把你的三色列表转换成三色列表。这很简单:

    @RequiredArgsConstructor
    @EqualsAndHashCode
    @ToString
    public static class Triplet {
        public static List<Triplet> listFrom(List<String> strings) {
            Preconditions.checkArgument(strings.size() % 3 == 0);
            final List<Triplet> result = new ArrayList<>();
            for (int i=0; i<strings.size(); i+=3) {
                result.add(new Triplet(
                        strings.get(i), strings.get(i+1), strings.get(i+2)));
            }
            return result;
        }
    
        public final String verb;
        public final String noun1;
        public final String noun2;
    }
    

    以上注释来自 project lombok 照他们说的做。如果你不想使用龙目,那么手动写下需要的内容。


    实际上就这些了,但我将进一步讨论前一个问题。上面的lambdas没有用,现在你有两个。

    您准备数据的方式如下

    final List<Triplet> tripletsOne = Triplet.listFrom(listOne);
    final List<Triplet> tripletsTwo = Triplet.listFrom(listTwo);
    final Map<String, List<Triplet>> mapOneByNoun1 = tripletsOne.stream()
            .collect(Collectors.groupingBy(t -> t.noun1));
    final Map<Object, List<Triplet>> mapOneByNoun2 = tripletsOne.stream()
            .collect(Collectors.groupingBy(t -> t.noun2));
    final List<Triplet> EMPTY = Collections.emptyList();
    

    这比我之前的方法更简单,因为 Collectors.groupingBy .

    像 z 在这两种情况下都发生,在最外层循环中使用它是有意义的

    for (final Triplet z : tripletsTwo) {
        for (final Triplet x : mapOneByNoun1.getOrDefault(z.noun1, EMPTY)) {
            for (final Triplet y : mapOneByNoun2.getOrDefault(z.noun2, EMPTY)) {
                doSomething(x, y);
            }
        }
    }
    

    这就是全部。

        2
  •  0
  •   Deepesh kumar Gupta    8 年前

    不知道你为什么要找lambda?请提供场景。。

    如果您的输入是具有快速随机访问的列表,则可以使用索引流解决您的问题:

    public static List<String> f(int n, List<String> input) {
    int fence = IntStream.range(0, input.size())
                         .filter(idx -> input.get(idx).equals("B")) // leave only B's
                         .skip(n-1)
                         .findFirst() // an index of n-th B
                         .getAsInt(); // with throw NoSuchElementException if not enough B's
    return input.subList(0, fence+1);
    }
    
        3
  •  0
  •   ajc    8 年前

    我认为你想了解如何构建你的 for 环

    写了一个简单的 对于 了解您的预期结果。这就是你想要实现的吗?

        // Considering we have these lists.. 
        // ArrayList<String> al1 = "IsA","Car","Vehicle","IsA","house","building"..
        // ArrayList<String> al2 = "IsA","house","home"..
    
        List<String> result = new ArrayList<>();
        for(int i=0; i<al1.size(); i+=3) {
            for(int j=0; j<al2.size(); j+=3) {
                if(i+2 < al1.size() && j+2 < al2.size()) {
                    if (al1.get(i).equals(al2.get(i)) && al1.get(i+1).equals(al2.get(i+1))) {
                        result.add(al1.get(i));
                        result.add(al1.get(i+1));
                        result.add(al1.get(i+2));
                    }
                }
            }
        }
    

    对于第二个检查,即检查名词2,可以更新条件以添加新的名词2检查-

    if (
    (al1.get(i).equals(al2.get(i)) && al1.get(i+1).equals(al2.get(i+1))) ||
    (al1.get(i).equals(al2.get(i)) && al1.get(i+2).equals(al2.get(i+2)))
    ) { .. }