算法练习,对象操纵

时间:2018-09-25 11:17:03

标签: javascript arrays javascript-objects

我正在做一些练习来提高我的算法技能,但是我为此感到挣扎,必须将数据数组格式化为匹配ExpectedStructure并将其放入newStructure中。如果有人可以给我提示如何使用很棒的ES6语法来做到这一点,谢谢!

https://jsbin.com/jazatimumo/edit?js,console,output

const data = [
  {
    name: "style",
    buckets: [
      {
        count: 38243,
        ratio: 4.476200397255031,
        name: "romantic",
        md5: "257927a09632991b08877ef6d29bec00"
      },
      {
        count: 14414,
        ratio: 1.6871048956942187,
        name: "retro",
        md5: "257927a09632991b08877ef6d29bec00"
      }
    ]
  },
  {
    name: "color",
    buckets: [
      {
        count: 26219,
        ratio: 8.1271048953942982,
        name: "blue",
        md5: "257927a09632991b08877ef6d29bec00",
        buckets: [
          {
            count: 11976,
            ratio: 3.1271048953942982,
            name: "lightblue",
            md5: "4457168314f0e9010d425f1d9db67937"
          }
        ]
      }
    ]
  }
]

let newStructure = [];

const expectedStructure = [
  {
    count: 38243,
    ratio: 4.476200397255031,
    name: "romantic",
    md5: "257927a09632991b08877ef6d29bec00",
    field: "style",
    label: "style = romantic"
  },
  {
    count: 14414,
    ratio: 1.6871048956942187,
    name: "retro",
    md5: "257927a09632991b08877ef6d29bec00",
    field: "style",
    label: "style = retro"
  },
  {
    count: 26219,
    ratio: 8.1271048953942982,
    name: "blue",
    md5: "257927a09632991b08877ef6d29bec00",
    field: "color",
    label: "color = blue"
  },
  {
    count: 11976,
    ratio: 3.1271048953942982,
    name: "lightblue",
    md5: "4457168314f0e9010d425f1d9db67937",
    field: "color",
    label: "color = lightblue"
  }
]

2 个答案:

答案 0 :(得分:1)

您可以在field上使用闭包,并对无限嵌套的buckets使用迭代和递归的方法。

var data = [{ name: "style", buckets: [{ count: 38243, ratio: 4.476200397255031, name: "romantic", md5: "257927a09632991b08877ef6d29bec00" }, { count: 14414, ratio: 1.6871048956942187, name: "retro", md5: "257927a09632991b08877ef6d29bec00" }] }, { name: "color", buckets: [{ count: 26219, ratio: 8.1271048953942982, name: "blue", md5: "257927a09632991b08877ef6d29bec00", buckets: [{ count: 11976, ratio: 3.1271048953942982, name: "lightblue", md5: "4457168314f0e9010d425f1d9db67937" }] }] }],
    result = data.reduce((r, { name: field, buckets }) =>
        buckets.reduce(function iter(s, { count, ratio, name, md5, buckets = [] }) {
            s.push({ count, ratio, name, md5, field, label: [field, name].join(' = ') });
            return buckets.reduce(iter, s);
        }, r), []);

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

对象的其余参数短一些。它可能需要更新的JS或babeljs

var data = [{ name: "style", buckets: [{ count: 38243, ratio: 4.476200397255031, name: "romantic", md5: "257927a09632991b08877ef6d29bec00" }, { count: 14414, ratio: 1.6871048956942187, name: "retro", md5: "257927a09632991b08877ef6d29bec00" }] }, { name: "color", buckets: [{ count: 26219, ratio: 8.1271048953942982, name: "blue", md5: "257927a09632991b08877ef6d29bec00", buckets: [{ count: 11976, ratio: 3.1271048953942982, name: "lightblue", md5: "4457168314f0e9010d425f1d9db67937" }] }] }],
    result = data.reduce((r, { name: field, buckets }) =>
        buckets.reduce(function iter(s, { buckets = [], ...rest }) {
            s.push({ ...rest, field, label: [field, rest.name].join(' = ') });
            return buckets.reduce(iter, s);
        }, r), []);

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

答案 1 :(得分:1)

这是使用递归实现此目标的一种方法。 我将这些代码分解为可读取代码的函数。

const data = [
  {
    name: "style",
    buckets: [
      {
        count: 38243,
        ratio: 4.476200397255031,
        name: "romantic",
        md5: "257927a09632991b08877ef6d29bec00"
      },
      {
        count: 14414,
        ratio: 1.6871048956942187,
        name: "retro",
        md5: "257927a09632991b08877ef6d29bec00"
      }
    ]
  },
  {
    name: "color",
    buckets: [
      {
        count: 26219,
        ratio: 8.1271048953942982,
        name: "blue",
        md5: "257927a09632991b08877ef6d29bec00",
        buckets: [
          {
            count: 11976,
            ratio: 3.1271048953942982,
            name: "lightblue",
            md5: "4457168314f0e9010d425f1d9db67937"
          }
        ]
      }
    ]
  }
]

let newStructure = [];


const expectedStructure = [
  {
    count: 38243,
    ratio: 4.476200397255031,
    name: "romantic",
    md5: "257927a09632991b08877ef6d29bec00",
    field: "style",
    label: "style = romantic"
  },
  {
    count: 14414,
    ratio: 1.6871048956942187,
    name: "retro",
    md5: "257927a09632991b08877ef6d29bec00",
    field: "style",
    label: "style = retro"
  },
  {
    count: 26219,
    ratio: 8.1271048953942982,
    name: "blue",
    md5: "257927a09632991b08877ef6d29bec00",
    field: "color",
    label: "color = blue"
  },
  {
    count: 11976,
    ratio: 3.1271048953942982,
    name: "lightblue",
    md5: "4457168314f0e9010d425f1d9db67937",
    field: "color",
    label: "color = lightblue"
  }
]
// Step 3: Take out the needed values and push it into the newStructure
// You can remove the buckets from the object and spread the rest of the properties
// ES6 ;)
function addToStructure (field, v) {
  const { buckets, ...all } = v;
  let obj = {
    ...all,
    field,
    label: `${field} = ${v.name}`
  };

  newStructure.push(obj);
}

// Step 2: Start traversing the buckets to add the object to newStructure
//
// Also, check if there's a nested bucket then 
// recurse over it and call traverse again
function traverse (field, buckets) {
    buckets.forEach((v) => {
      addToStructure(field, v);
      v.buckets && traverse(field, v.buckets);
    });
}

// Step 1: Run a loop over the whole data
data.forEach((value) => {
  let field = value.name;
  traverse(field, value.buckets);
});

console.log('IS EQUAL TO EXPECTED STRUCTURE ? =', JSON.stringify(newStructure) === JSON.stringify(expectedStructure))
console.log(newStructure);
.as-console-wrapper { max-height: 100% !important; top: 0; }