我该如何改变这个?

时间:2018-06-09 08:07:56

标签: javascript ramda.js

我想为以下转换找到一个很好的优雅解决方案。如何以最简单的方式使用函数库Ramda来实现最佳效果?

const data = [
  {
    id: 'a',
  },
  {
    id: 'b',
    routes: [
      {
        id: 'c',
      },
      {
        id: 'd',
        routes: [
          {
            id: 'e',
          }
        ]
      }
    ]
  }
];

const expected = [
  {
    id: 'a',
  },
  {
    id: 'b',
  },
  {
    id: 'c',
  },
  {
    id: 'd',
  },
  {
    id: 'e',
  }
];

3 个答案:

答案 0 :(得分:2)

这是一个使用reduce和递归的vanilla JS解决方案:



const data = [
  {
    id: 'a',
  },
  {
    id: 'b',
    routes: [
      {
        id: 'c',
      },
      {
        id: 'd',
        routes: [
          {
            id: 'e',
          }
        ]
      }
    ]
  }
];

const transform = arr => arr.reduce((a, { id, routes }) => (
  [...a, { id }, ...transform(routes || [])]
), []);
console.log(transform(data));




或者,不是每次都创建新数组,而是简单地推送到现有数组:



const data = [{
    id: 'a',
  },
  {
    id: 'b',
    routes: [{
        id: 'c',
      },
      {
        id: 'd',
        routes: [{
          id: 'e',
        }]
      }
    ]
  }
];

const transform = (arr, pushTo = []) => arr.reduce((a, { id, routes }) => {
  a.push({ id });
  if (routes) transform(routes, a);
  return a;
}, pushTo);
console.log(transform(data));




使用嵌套属性的变量而不是routes硬编码:



const data = [{
    id: 'a',
  },
  {
    id: 'b',
    routes: [{
        id: 'c',
      },
      {
        id: 'd',
        routes: [{
          id: 'e',
        }]
      }
    ]
  }
];

const transform = (arr, prop, pushTo = []) => arr.reduce((a, item) => {
  const nested = item[prop];
  a.push({ id: item.id });
  if (nested) transform(nested, prop, a);
  return a;
}, pushTo);
console.log(transform(data, 'routes'));




答案 1 :(得分:1)

JS中没有太多传播的解决方案

function getFlat(array = []) {
    return array.reduce((r, { id, routes }) => r.concat({ id }, getFlat(routes)), []);
}

const data = [{ id: 'a', }, { id: 'b', routes: [{ id: 'c', }, { id: 'd', routes: [{ id: 'e', }] }] }];

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

使用对象的rest参数获取对象的所有属性,exept routes返回。

function getFlat(array = []) {
    return array.reduce((r, { routes, ...o }) => r.concat(o, getFlat(routes)), []);
}

const data = [{ id: 'a', foo: 1 }, { id: 'b', routes: [{ id: 'c' }, { id: 'd', routes: [{ id: 'e', bar: 2 }] }] }];

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

答案 2 :(得分:1)

此处其他建议的替代方法是使用R.chain展平每组嵌套路线。

const fn = R.chain(({routes = [], ...rest}) => [{...rest}, ...fn(routes)])

一旦Array.prototype.flatMap变得容易获得,这种方法也可以用普通的JS实现。

const fn = (xs = []) => xs.flatMap(({routes, ...rest}) => [{...rest}, ...fn(routes)])