我如何强行使用对象的值?

时间:2019-12-15 09:11:40

标签: javascript

我有一组具有数字坐标(x,y)和名称的对象。

我想对x和y在一个范围内的每个值强行使用x和y。 (说[0,1,2,3,4,5])

var variables = {"aboutTitle_x": 0, "aboutTitle_y": 0}
let f = (a, b) => [].concat(...a.map(a => b.map(b => [].concat(a, b))));
let cartesian = (a, b, ...c) => b ? cartesian(f(a, b), ...c) : a;


var candidates = cartesian(Object.keys(variables), [0, 1,2,3,4,5]);
console.log(candidates);

我正在使用笛卡尔积,这给了我所有的任务,就像这样:

["aboutTitle_x", 0]
["aboutTitle_x", 1]
["aboutTitle_x", 2]
["aboutTitle_x", 3]
["aboutTitle_x", 4]
["aboutTitle_x", 5]
["aboutTitle_y", 0]
["aboutTitle_y", 1]
["aboutTitle_y", 2]
["aboutTitle_y", 3]

如何迭代(aboutTitle_x,aboutTitle_y)的潜在组合。我想要的是这样的东西:

{aboutTitle_x: 0, aboutTitle_y: 0}
{aboutTitle_x: 0, aboutTitle_y: 1}
{aboutTitle_x: 0, aboutTitle_y: 2}
{aboutTitle_x: 0, aboutTitle_y: 3}
{aboutTitle_x: 0, aboutTitle_y: 4}

2 个答案:

答案 0 :(得分:1)

您可以采取略有不同的方法,并为对象存储可能的值(也可以嵌套),结果您将获得给定属性的所有可能值的数组。

function getCartesian(object) {
    return Object.entries(object).reduce((r, [k, v]) => {
        var temp = [];
        r.forEach(s =>
            (Array.isArray(v) ? v : [v]).forEach(w =>
                (w && typeof w === 'object' ? getCartesian(w) : [w]).forEach(x =>
                    temp.push(Object.assign({}, s, { [k]: x }))
                )
            )
        );
        return temp;
    }, [{}]);
}

var values = [0, 1, 2, 3, 4, 5],
    data = { aboutTitle_x: values, aboutTitle_y: values },
    cartesian = getCartesian(data);

console.log(cartesian);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:1)

您可以使用递归方法,其中对值使用for循环,但通过递归增加键,还可以将对象引用作为当前值传递。

var variables = {
  "aboutTitle_x": 0,
  "aboutTitle_y": 0
}

function cartesian(keys, values, k = 0, tmp = {}) {
  const r = [];

  if (k >= keys.length) {
    r.push({ ...tmp });
    return r;
  }

  for (let i = 0; i < values.length; i++) {
    Object.assign(tmp, {[keys[k]]: values[i]})
    r.push(...cartesian(keys, values, k + 1, tmp))
  }

  return r;
}


var candidates = cartesian(Object.keys(variables), [0, 1, 2, 3, 4, 5]);
console.log(candidates);

您也可以使用reduce方法来代替for循环。

var variables = {
  "aboutTitle_x": 0,
  "aboutTitle_y": 0
}

function cartesian(keys, values, k = 0, tmp = {}) {
  return values.reduce((r, e) => {
    tmp[keys[k]] = e;

    if (k >= keys.length - 1) {
      r.push({ ...tmp});
      return r;
    }

    r.push(...cartesian(keys, values, k + 1, tmp))
    return r;
  }, [])
}


var candidates = cartesian(Object.keys(variables), [0, 1, 2, 3, 4, 5]);
console.log(candidates);

您还可以将递归与 generator 一起使用,这将使您可以控制每次迭代。

var variables = {
  "aboutTitle_x": 0,
  "aboutTitle_y": 0
}

function* cartesian(keys, values, k = 0, tmp = {}) {
  if (k >= keys.length) {
    yield { ...tmp }
  } else {
    for (let i = 0; i < values.length; i++) {
      Object.assign(tmp, { [keys[k]]: values[i] })
      yield* cartesian(keys, values, k + 1, tmp)
    }
  }
}

var it = cartesian(Object.keys(variables), [0, 1, 2, 3, 4, 5]);

for (let i of it) {
  console.log(i)
}