如何展平仅定位到指定子项的数组?

时间:2018-04-20 16:19:54

标签: javascript arrays lodash

我有一个类似于此的集合:

[
    {
        "name": "Item 1",
        "id": 200244,
        "siblings": []
    }, {
        "name": "Item 2",
        "id": 200134,
        "siblings": []
    }, {
        "name": "Item 3",
        "id": 200179,
        "siblings": [
            {
                "name": "Item 3 SubItem 1",
                "id": 200146
            }
        ]
    }, {
        "name": "Item 4",
        "id": 200133,
        "siblings": []
    }, {
        "name": "Item 5",
        "id": 200135,
        "siblings": [
            {
                "name": "Item 5 SubItem 1",
                "id": 200146
            }
        ]
    }
]

我正在尝试将其展平,以便将子siblings值提升到级别时,它们不为空。最终结构如下所示:

[
    {
        "name": "Item 1",
        "id": 200244
    }, {
        "name": "Item 2",
        "id": 200134
    }, {
        "name": "Item 3",
        "id": 200179
    }, {
        "name": "Item 3 SubItem 1",
        "id": 200146
    }, {
        "name": "Item 4",
        "id": 200133
    }, {
        "name": "Item 5",
        "id": 200135
    }, {
        "name": "Item 5 SubItem 1",
        "id": 200146
    }
]

有关从何处入手的建议?我玩弄了Lodash的flatMap没有成功。

5 个答案:

答案 0 :(得分:1)

挑选flatMap是正确的选择

const data =
  ...

const flatMap = (f, xs = []) =>
  xs.reduce ((acc, x) => acc.concat (f (x)), [])

flatMap (({ siblings = [], ...item }) => [ item, ...siblings ], data)
// [ { name: 'Item 1', id: 200244 }
// , { name: 'Item 2', id: 200134 }
// , { name: 'Item 3', id: 200179 }
// , { name: 'Item 3 SubItem 1', id: 200146 }
// , { name: 'Item 4', id: 200133 }
// , { name: 'Item 5', id: 200135 }
// , { name: 'Item 5 SubItem 1', id: 200146 }
// ]

使用lodash' s _.flatMap几乎与我们上面的实现完全相同 - 只切换参数的顺序

const data =
  ...

const result = 
  _.flatMap ( data
            , ({ siblings = [], ...item }) => [ item, ...siblings ]
            )

console.log (result)
// [ { name: 'Item 1', id: 200244 }
// , { name: 'Item 2', id: 200134 }
// , { name: 'Item 3', id: 200179 }
// , { name: 'Item 3 SubItem 1', id: 200146 }
// , { name: 'Item 4', id: 200133 }
// , { name: 'Item 5', id: 200135 }
// , { name: 'Item 5 SubItem 1', id: 200146 }
// ]

这是使用此处提供的flatMap实施的完整程序演示。随意使用它或您选择的任何其他实现:)



const flatMap = (f, xs = []) =>
  xs.reduce ((acc, x) => acc.concat (f (x)), [])
  
const data =
  [ { name: "Item 1"
    , id: 200244
    , siblings: []
    }
  , { name: "Item 2"
    , id: 200134
    , siblings: []
    }
  , { name: "Item 3"
    , id: 200179
    , siblings:
      [ { name: "Item 3 SubItem 1"
        , id: 200146
        }
      ]
    }
  , { name: "Item 4"
    , id: 200133
    , siblings: []
    }
  , { name: "Item 5"
    , id: 200135
    , siblings:
      [ { name: "Item 5 SubItem 1"
        , id: 200146
        }
      ]
    }
  ]

const result = 
  flatMap (({ siblings = [], ...item }) => [ item, ...siblings ], data)

console.log (result)
// [ { name: 'Item 1', id: 200244 }
// , { name: 'Item 2', id: 200134 }
// , { name: 'Item 3', id: 200179 }
// , { name: 'Item 3 SubItem 1', id: 200146 }
// , { name: 'Item 4', id: 200133 }
// , { name: 'Item 5', id: 200135 }
// , { name: 'Item 5 SubItem 1', id: 200146 }
// ]




答案 1 :(得分:0)

您可以使用reduce并使用concat添加兄弟姐妹



let arr=[{"name":"Item 1","id":200244,"siblings":[]},{"name":"Item 2","id":200134,"siblings":[]},{"name":"Item 3","id":200179,"siblings":[{"name":"Item 3 SubItem 1","id":200146}]},{"name":"Item 4","id":200133,"siblings":[]},{"name":"Item 5","id":200135,"siblings":[{"name":"Item 5 SubItem 1","id":200146}]}];

let result = arr.reduce((c, {siblings,...r}) => {
  c.push(r);                    //Push the {name,id}
  c = c.concat(siblings);       //Concat the siblings
  return c;
}, []);

console.log(result);




Doc:.reduce()

答案 2 :(得分:0)

您可以使用Lodash reduce()pick()方法创建递归函数,以展平任何深度的数组。



const data = [{"name":"Item 1","id":200244,"siblings":[]},{"name":"Item 2","id":200134,"siblings":[]},{"name":"Item 3","id":200179,"siblings":[{"name":"Item 3 SubItem 1","id":200146}]},{"name":"Item 4","id":200133,"siblings":[]},{"name":"Item 5","id":200135,"siblings":[{"name":"Item 5 SubItem 1","id":200146}]}]

const flatten = data => {
  return _.reduce(data, (r, e) => {
    r.push(_.pick(e, ['name', 'id']))
    if (e.siblings) r.push(...flatten(e.siblings))
    return r;
  }, [])
}

console.log(flatten(data))

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
&#13;
&#13;
&#13;

答案 3 :(得分:0)

将lodash的_.flatMapDeep()object destructuring

一起使用

const data = [{"name":"Item 1","id":200244,"siblings":[]},{"name":"Item 2","id":200134,"siblings":[]},{"name":"Item 3","id":200179,"siblings":[{"name":"Item 3 SubItem 1","id":200146}]},{"name":"Item 4","id":200133,"siblings":[]},{"name":"Item 5","id":200135,"siblings":[{"name":"Item 5 SubItem 1","id":200146}]}];

const result= _.flatMapDeep(data, ({ siblings, ...rest }) => [rest, siblings]);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

答案 4 :(得分:0)

虽然它没有使用Lodash或更现代的JS技术,但这是一种提升和转移的简单方法。不考虑订购..

var json = [{
  "name": "Item 1",
  "id": 200244,
  "siblings": []
}, {
  "name": "Item 2",
  "id": 200134,
  "siblings": []
}, {
  "name": "Item 3",
  "id": 200179,
  "siblings": [{
    "name": "Item 3 SubItem 1",
    "id": 200146
  }]
}, {
  "name": "Item 4",
  "id": 200133,
  "siblings": []
}, {
  "name": "Item 5",
  "id": 200135,
  "siblings": [{
    "name": "Item 5 SubItem 1",
    "id": 200146
  }]
}];

for (var obj in json) {
  var nestedObj = json[obj];
  if (nestedObj.hasOwnProperty('siblings')) {
    if (nestedObj.siblings.length > 0) {
      for (var sibling in nestedObj.siblings) {
        var siblingItem = nestedObj.siblings[sibling];
        json.push(siblingItem);
      }
    }
    delete nestedObj['siblings'];
  }
}

console.log(json);