Combining arrays for use cases

后端 未结 3 1687
再見小時候
再見小時候 2021-01-06 23:13

Node.js app, writing validation tests. Given the following:

var obj = { foo: null, bar: null, baz: null},
    values = [ 0, 1];

I need to

相关标签:
3条回答
  • 2021-01-06 23:43

    One way is to count from "000" to "999" in a values.length-based system:

    keys = ['foo','bar','baz']
    values = ['A', 'B']
    
    
    width = keys.length
    base = values.length
    out = []
    
    for(var i = 0; i < Math.pow(base, width); i++) {
      
      var d = [], j = i;
      
      while(d.length < width) {
        d.unshift(j % base)
        j = Math.floor(j / base)
      }
      
      var p = {};
      
      for(var k = 0; k < width; k++)
        p[keys[k]] = values[d[k]]
    
      out.push(p)
    }  
    
    
    document.write('<pre>'+JSON.stringify(out,0,3))

    Update for products:

    'use strict';
    
    let
        keys = ['foo', 'bar', 'baz'],
        values = [
            ['A', 'B'],
            ['a', 'b', 'c'],
            [0, 1]
        ];
    
    
    let zip = (h, t) =>
        h.reduce((res, x) =>
            res.concat(t.map(y => [x].concat(y)))
        , []);
    
    let product = arrays => arrays.length
        ? zip(arrays[0], product(arrays.slice(1)))
        : [[]];
    
    let combine = (keys, values) =>
        keys.reduce((res, k, i) =>
            (res[k] = values[i], res)
            , {});
    
    let z = product(values).map(v => combine(keys, v));
    
    z.map(x => document.write('<pre>'+JSON.stringify(x)+'</pre>'))

    0 讨论(0)
  • 2021-01-07 00:07

    This is a non-recursive version of what you want:

    function createRange(keys, values) {
      if (typeof values[0] !== typeof [])
        values = keys.map(k => values);
      var pointer = {};
      var repeats = 1;
      keys.forEach((k, i) => {
        var vLen = values[i].length;
        repeats *= vLen;
        pointer[k] = {
          get value() {
              return values[i][pointer[k].current]
            },
            current: 0,
            period: Math.pow(vLen, i),
            inc: function() {
              var ptr = pointer[k];
              ptr.current++;
              if (ptr.current < vLen) return;
    
              ptr.current = 0;
              if (i + 1 === keys.length) return;
    
              var nk = keys[i + 1];
              pointer[nk].inc()
            }
        };
      });
      var result = [];
      for (var i = 0; i < repeats; i++) {
        var o = {};
        result.push(o);
        keys.forEach(k => o[k] = pointer[k].value)
        pointer[keys[0]].inc();
      }
      return result;
    }
    
    var objKeys = ['u', 'v', 'w', 'x', 'y', 'z'];
    var objValues = [
      ['1', '2', '3'],
      ['a', 'b', 'c'],
      ['foo', 'bar', 'baz'],
      [1, 3, 2],
      ['test', 'try', 'catch'],
      ['Hello', 'World'],
    ];
    
    var range = createRange(objKeys, objValues);
    range.map(v => document.write(JSON.stringify(v).big()))

    0 讨论(0)
  • 2021-01-07 00:09

    Solution for any object length and any values.

    Please note, undefined values do not show up.

    function buildObjects(o) {
        var keys = Object.keys(o),
            result = [];
    
        function x(p, tupel) {
            o[keys[p]].forEach(function (a) {
                if (p + 1 < keys.length) {
                    x(p + 1, tupel.concat(a));
                } else {
                    result.push(tupel.concat(a).reduce(function (r, b, i) {
                        r[keys[i]] = b;
                        return r;
                    }, {}));
                }
            });
        }
    
        x(0, []);
        return result;
    }
    
    document.write('<pre>' + JSON.stringify(buildObjects({
        foo: [0, 1, 2],
        bar: [true, false],
        baz: [true, false, 0, 1, 42]
    }), 0, 4) + '</pre>');

    0 讨论(0)
提交回复
热议问题