【问题标题】:How to combine two arrays as a cartesian product?如何将两个数组组合为笛卡尔积?
【发布时间】:2016-04-21 22:23:10
【问题描述】:

我有

array1 = [1,2,3,4,5];
array2 = ["one","two","three","four","five"];

我想得到array3,其中array1 的所有元素与array2 的第一个(和其他)元素等等。

例如:

array3 = ["one 1", "two 1", "three 1", "four 1", "five 1", "one 2", "two 2", "three 2", "four 2", "five 2"...]

我知道我需要使用 for 循环,但我不知道该怎么做。

【问题讨论】:

  • 如果你是下划线或lodash,一个简单的zipWith 可以工作:_.zipWith(array1, array2, function(a,b) { return a + ' ' + b; });

标签: javascript arrays loops cartesian-product


【解决方案1】:

您可以使用两个 for 循环:

var array1 = [1,2,3,4,5];
var array2 = ["one","two","three","four","five"];

var array3 = [];
for (var i = 0; i < array1.length; i++) {
    for (var j = 0; j < array2.length; j++) {
        array3.push(array2[j] + ' ' + array1[i]);
    }
}

console.log(array3);

【讨论】:

    【解决方案2】:

    您可以使用Array.prototype.forEach() 对数组进行迭代。

    forEach() 方法对每个数组元素执行一次提供的函数。

    var array1 = [1, 2, 3, 4, 5],
        array2 = ["one", "two", "three", "four", "five"],
        result = [];
    
    array1.forEach(function (a) {
        array2.forEach(function (b) {
            result.push(b + ' ' + a);
        });
    });
    
    document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

    【讨论】:

      【解决方案3】:

      reducemapconcat 的另一种方式

      片段基于@Nina Scholz

      var array1 = [1, 2, 3, 4, 5],
          array2 = ["one", "two", "three", "four", "five"];
      
      var result = array1.reduce(function (acc, cur) {
          return acc.concat(array2.map(function (name) {
              return name + ' ' + cur;
          }));
      },[]);
      
      document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

      【讨论】:

        【解决方案4】:

        还有循环选项:

        var array2 = [1,2,3,4,5],
        array1 = ["one","two","three","four","five"],
        m = [];
        for(var a1 in array1){  
          for(var a2 in array2){
              m.push( array1[a1]+ array2[a2] );    
          }
        }
        console.log(m);
        
        【解决方案5】:

        试试(JS)

        function myFunction(){
                    var F = [1, 2, 3, 4,5];
                    var S = ["one", "two", "three", "four", "five"];
                    var Result = [];
        
                   var k=0;
                    for (var i = 0; i < F.length; i++) {
                        for (var j = 0; j < S.length; j++) {
                            Result[k++] = S[j] + " " + F[i];
                        }
                    }
        
                    console.log(Result);
                }
        

        【讨论】:

        • 这是一个 JS 问题。 OP 或许能够从中推断出代码,但我认为它没有用。
        • 已更正请检查
        【解决方案6】:

        array1.lengtharray2.length 相等时,您可以使用此方法。

        var array1 = [1, 2, 3, 4, 5];
        var array2 = ["one", "two", "three", "four", "five"];
        var length = array1.length;
        var array3 = new Array(Math.pow(length, 2)).fill(0).map((v, i) => array2[i % length] + ' ' + array1[i / length << 0]);
        
        
        document.body.textContent = JSON.stringify(array3);

        【讨论】:

        • 如果数组长度不同怎么办?
        • @Grundy 这个问题没有提到。
        • 是的,但我认为你应该添加改进,这适用于具有相同长度的数组
        【解决方案7】:

        由于这不是语言内置的,这里有一个与内置zip签名相似的简单函数:

        func cartesianProduct<Sequence1, Sequence2>(_ sequence1: Sequence1, _ sequence2: Sequence2) -> [(Sequence1.Element, Sequence2.Element)]
            where Sequence1 : Sequence, Sequence2 : Sequence
        {
            var result: [(Sequence1.Element, Sequence2.Element)] = .init()
            sequence1.forEach { value1 in
                sequence2.forEach { value2 in
                    result.append((value1, value2))
                }
            }
            return result
        }
        
        print(Array(zip([1, 2, 3], ["a", "b"]))) // [(1, "a"), (2, "b")]
        print(cartesianProduct([1, 2, 3], ["a", "b"])) // [(1, "a"), (1, "b"), (2, "a"), (2, "b"), (3, "a"), (3, "b")]
        

        在你的情况下,你可以这样做:

        cartesianProduct([1,2,3,4,5], ["one","two","three","four","five"])
          .map { "\($0.1) \($0.0)" }
        

        甚至:

        cartesianProduct(1...5, ["one","two","three","four","five"])
          .map { "\($0.1) \($0.0)" }
        

        两者都会产生序列:

        ["one 1", "two 1", "three 1", "four 1", "five 1", "one 2", "two 2", "three 2", "four 2", "five 2", ...]
        

        由于这在集合的元素上很常见,因此我还创建了这两个功能扩展:

        extension Collection {
            /// O(n^2)
            func pairElementToEveryOtherElement() -> [(Self.Element, Self.Element)] {
                var result = [(Self.Element, Self.Element)]()
                for i in indices {
                    var j = index(after: i)
                    while j != endIndex {
                        result.append((self[i], self[j]))
                        j = index(after: j)
                    }
                }
                return result
            }
        
            /// O(n)
            public func pairElementToNeighbors() -> [(Self.Element, Self.Element)] {
                if isEmpty {
                    return .init()
                }
        
                var result: [(Self.Element, Self.Element)] = .init()
                var i = startIndex
                while index(after: i) != endIndex {
                    result.append((self[i], self[index(after: i)]))
                    i = index(after: i)
                }
                return result
            }
        }
        

        这些可以像下面这样使用:

        let inefficientHasDuplicatesCheck = myCollection
          .pairElementToEveryOtherElement()
          .contains { $0.0 == $0.1 }
        

        【讨论】:

          猜你喜欢
          • 2017-03-05
          • 2016-02-24
          • 2011-12-18
          • 2011-01-31
          • 2020-12-10
          • 2016-07-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多