如何使用for语句获取数组或arraylist中的所有n组三个连续元素?

时间:2010-04-30 04:29:46

标签: java c++ c coding-style code-generation

我正在尝试进行凸壳方法,小问题是我需要获得所有三个连续顶点的集合,如下所示:

private void isConvexHull(Ponto[] points) {
        Arrays.sort(points);
        for (int i = 0; i <points.length; i++) {
            isClockWise(points[i],points[i+1],points[i+2]);
        }
     //... 
    }

我总是做一些我不认为干净代码的事情。请帮助我找到一种或多种方法吗?我希望它是循环的,即,如果我的fisrt点是数组中的最后一个元素,第二个元素将是列表中的第3个元素,该集合中的第3个元素将是列表中的第2个元素, 等等。他们必须连续,这就是全部。

2 个答案:

答案 0 :(得分:5)

余下的“技巧”

您可以使用%“技巧”(%是余数运算符JLS 15.17.3)进行循环索引。在这里,我将使用String来说明一般概念。

    String s = "ABCDE";
    final int L = s.length();
    for (int i = 0; i < L; i++) {
        System.out.format("%c%c%c ",
            s.charAt(i),
            s.charAt((i + 1) % L),
            s.charAt((i + 2) % L)
        );
    } // prints "ABC BCD CDE DEA EAB "

Iterator方法

如果你经常进行这种三重态处理,那么拥有Iterator<PointTriplet>或类似的东西将是一个更好的整体设计。

这是一个原型来说明这个想法:

import java.util.*;

public class CircSubArray {
    static <T> Iterator<T[]> circularIterator(final T[] arr, final int K) {
        return new Iterator<T[]>() {
            int index = 0;
            final int L = arr.length;
            T[] sub = Arrays.copyOf(arr, K); // let it do the dirty work!

            @Override public boolean hasNext() {
                return index < L;
            }
            @Override public T[] next() {
                for (int i = 0; i < K; i++) {
                    sub[i] = arr[(index + i) % L];
                }
                index++;
                return sub; // we always overwrite; no need to .clone()
            }
            @Override public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }   
    public static void main(String[] args) {
        String[] arr = { "s1", "s2", "s3", "s4", "s5", "s6" };

        Iterator<String[]> iter = circularIterator(arr, 4);
        while (iter.hasNext()) {
            System.out.println(Arrays.toString(iter.next()));
        }
    }
}

打印:

[s1, s2, s3, s4]
[s2, s3, s4, s5]
[s3, s4, s5, s6]
[s4, s5, s6, s1]
[s5, s6, s1, s2]
[s6, s1, s2, s3]

基于List的解决方案

正如 Effective Java 2nd Edition 所述,第25项:首选列表到数组。这是一个在K-1末尾冗余存储第一个List元素的解决方案,然后一次只使用subList来获取K个元素。

    String[] arr = { "s1", "s2", "s3", "s4", "s5", "s6" };

    final int L = arr.length;
    final int K = 3;
    List<String> list = new ArrayList<String>(Arrays.asList(arr));
    list.addAll(list.subList(0, K-1));

    for (int i = 0; i < L; i++) {
        System.out.println(list.subList(i, i + K));
    }

打印:

[s1, s2, s3]
[s2, s3, s4]
[s3, s4, s5]
[s4, s5, s6]
[s5, s6, s1]
[s6, s1, s2]

由于subList是一个视图,因此不必执行基于阵列的解决方案所做的O(K)转换。这也显示了List对数组的表达能力。

答案 1 :(得分:2)

简单地记住前两个点,从结束开始,并在每次迭代时移动它们。

private static boolean isConvexHull(Ponto[] points)
{
    final int len = points.length;
    if (len < 3) return false;
    Arrays.sort(points);

    Ponto p1 = points[len - 2];
    Ponto p2 = points[len - 1];
    for (Ponto p3 : points)
    {
        if (!isClockWise(p1, p2, p3)) return false;
        p1 = p2;
        p2 = p3;
    }
    return true;
}

顺便问一下,你究竟如何对数组进行排序?什么是排序标准?