V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Luckyray
V2EX  ›  程序员

多个数组,每个有多个元素,彼此两两结合,怎么写比较优雅?

  •  
  •   Luckyray · 2018-05-15 15:56:54 +08:00 · 4612 次点击
    这是一个创建于 2394 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我想写接口的单元测试,每个参数都给了几个测试数据,不知道该怎么写了,想问问大家除了 N 个 for 循环还有什么办法?

    最好不是脚本语言的奇技淫巧...Java 没辣么灵活。
    24 条回复    2019-07-06 21:31:00 +08:00
    agagega
        1
    agagega  
       2018-05-15 16:16:24 +08:00   ❤️ 1
    你想实现的操作,如果我没有理解错的话,在脚本语言或者函数式语言里叫做 zip。

    [1, 2, 3, 4].zip([5, 6, 7, 8])
    # => [[1, 5], [2, 6], [3, 7], [4, 8]]

    Java 的话,可以看看 StackOverflow#3833814
    Luckyray
        2
    Luckyray  
    OP
       2018-05-15 16:38:43 +08:00
    @agagega 不太一样,我的意思不知道是不是应该叫“全结合”,就是排列组合里面的组合,15,16,17,18,25,26...这样,4*4 应该是 16 个结果。
    YenvY
        3
    YenvY  
       2018-05-15 16:41:12 +08:00
    看手写循环说的大概是排列组合?
    function test(arys, states) {
    if (arys.length) {

    arys.forEach(
    YenvY
        4
    YenvY  
       2018-05-15 16:49:02 +08:00   ❤️ 1
    function test(arys, states) {
    if (arys.length) {
    for (const elmt of arys[0]) {
    states.push(elmt);
    test(arys.slice(1), states)
    }
    states.pop();
    }
    else {
    console.log(states);
    states.pop();
    }
    }
    pinger
        5
    pinger  
       2018-05-15 17:02:36 +08:00
    function biu() {
    return Array.prototype.reduce.call(arguments, function(i, j) {
    var result = [];
    a.forEach(function(i) {
    b.forEach(function(j) {
    result.push(i.concat([j]))
    })
    });
    return result;
    }, [[]])
    }

    biu([1,2,3],[4,5,6],[7,8,9])
    pinger
        6
    pinger  
       2018-05-15 17:06:00 +08:00   ❤️ 1
    function biu() {
    return Array.prototype.reduce.call(arguments, function(a, b) {
    var result = [];
    a.forEach(function(a) {
    b.forEach(function(b) {
    result.push(a.concat([b]))
    })
    });
    return result;
    }, [[]])
    }

    biu([1,2,3],[4,5,6],[7,8,9])
    重发一次
    ycz0926
        7
    ycz0926  
       2018-05-15 17:06:59 +08:00
    $ zip [1..10] [20..30]
    [(1,20) ...]
    marcong95
        8
    marcong95  
       2018-05-15 17:11:29 +08:00   ❤️ 2
    笛卡尔积?
    CRVV
        9
    CRVV  
       2018-05-15 17:27:43 +08:00
    >>> a = [1, 2, 3, 4]
    >>> b = [5, 6, 7, 8]
    >>> [(x, y) for x in a for y in b]
    [(1, 5), (1, 6), (1, 7), (1, 8), (2, 5), (2, 6), (2, 7), (2, 8), (3, 5), (3, 6), (3, 7), (3, 8), (4, 5), (4, 6), (4, 7), (4, 8)]

    Python 和 Haskell 的正常写法,算不上奇技淫巧吧
    Java 的正常写法当然就是嵌套循环,我觉得足够优雅了
    covering
        10
    covering  
       2018-05-15 17:59:15 +08:00
    lz 是想要一个 generator 吧?

    class XG{public X next();}

    while (XG.next() != null) { test(X)}
    Luckyray
        11
    Luckyray  
    OP
       2018-05-15 17:59:35 +08:00
    @marcong95 对对,数学没学好话都说不清楚...
    RicardoScofileld
        12
    RicardoScofileld  
       2018-05-15 18:33:11 +08:00
    拿 numpy 或 pandas 处理一下?
    RicardoScofileld
        13
    RicardoScofileld  
       2018-05-15 18:34:24 +08:00
    不过我记得 collections 里面有一个方法可以实现,叫 com*什么来着想不起来了
    Semesse
        14
    Semesse  
       2018-05-15 18:58:06 +08:00 via Android
    python 的 itertools 就有 product
    gihnius
        15
    gihnius  
       2018-05-15 18:58:33 +08:00 via iPhone   ❤️ 1
    Ruby:

    a.product(b)
    3pmtea
        16
    3pmtea  
       2018-05-15 19:12:38 +08:00
    既然是 Java,那就 N 个 for 就完事儿了

    如果你想搞什么骚操作的话,有这么个思路:
    设计一个类,表示 N 位、size-进制的数,就可以只用一个 for,遍历这个对象的值域,达到枚举的目的
    mengyaoss77
        18
    mengyaoss77  
       2018-05-15 19:34:48 +08:00
    用 python 预处理一遍,再用 Java 去取呗
    motoko
        19
    motoko  
       2018-05-15 19:40:49 +08:00
    不想用循环,那就递归嘛~~
    def combine(pre, v2, idx):
    if idx >= len(v2):
    print pre
    return
    v1, idx = v2[idx], idx + 1
    for c in v1:
    combine(pre + str(c), v2, idx)

    if __name__ == '__main__':
    v2 = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 'a', 'b']]
    combine('', v2, 0)
    ~
    wanganjun
        20
    wanganjun  
       2018-05-15 19:57:39 +08:00 via iPhone
    偷懒的办法:把数组元素插入到内存表里面,一个数组一个表,然后连表查询......
    shalk
        21
    shalk  
       2018-05-15 21:05:25 +08:00 via iPhone   ❤️ 1
    n 个数组,把迭代器都取出来. 做成一个列表,整数进位一样. 例如 n 为 4,迭代器数组指向的是 0,0,0,0,再一次就是 0,0,0,1 当低位,hasnext 到头了,就进位,下一个迭代器移动,并且把本迭代器回拨到 0. 最后整个封装成一个 generator
    wr410
        22
    wr410  
       2018-05-15 21:54:06 +08:00   ❤️ 1
    你这个直接说“ CrossJoin ”或者笛卡尔积就专业了。

    具体实现上面都有,就不班门弄斧了。
    shalk
        23
    shalk  
       2018-05-15 22:45:39 +08:00
    电脑上补代码
    ```


    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;

    public class Permutation {
    interface Generator<T> {
    T next();

    boolean hasNext();
    }

    static class PermutationGenerator implements Generator<List<Integer>> {
    final private int[] index;
    final List<List<Integer>> nums;
    private boolean hasNext = true;

    public PermutationGenerator(List<List<Integer>> nums) {
    this.nums = nums;
    index = new int[nums.size()];
    }

    @Override
    public List<Integer> next() {
    List<Integer> ret = new ArrayList<>();
    if (!hasNext)
    return ret;

    for (int i = 0; i < index.length; i++) {
    ret.add(nums.get(i).get(index[i]));
    }

    int resetCount = 0;
    for (int i = 0; i < index.length; i++) {
    if (index[i] < nums.get(i).size() - 1) {
    index[i]++;
    break;
    } else {
    index[i] = 0;
    resetCount++;
    }
    }

    if (resetCount == index.length) {
    hasNext = false;
    }
    return ret;
    }

    @Override
    public boolean hasNext() {
    return hasNext;
    }
    }


    public static void main(String[] args) {
    List<List<Integer>> data = Arrays.asList(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), Arrays.asList(7, 8, 9));
    Generator<List<Integer>> gen = new PermutationGenerator(data);
    while (gen.hasNext()) {
    System.out.println(gen.next());
    }
    }
    }

    ```
    BBCCBB
        24
    BBCCBB  
       2019-07-06 21:31:00 +08:00
    你可以参考 leetcode 17 题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1125 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 18:56 · PVG 02:56 · LAX 10:56 · JFK 13:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.