web-dev-qa-db-ja.com

配列およびネストされた子配列でのlodashプロパティ検索

私はこの配列を持っています:

[
    {
        id: 1,
        name: 'test 1',
        children: []
    },
    {
        id: 2,
        name: 'test 2',
        children: [
            {
                id: 4,
                name: 'test 4'
            }
        ]
    },
    {
        id: 3,
        name: 'test 3',
        children: []
    }
]

この配列およびネストされたid配列の両方でchildrenプロパティでフィルタリングするにはどうすればよいですか?

たとえば、id = 3を検索するとtest 3オブジェクトが返され、id = 4を検索するとtest 4オブジェクトが返されます。

16
Mirza Delic

Lodashを使用すると、次のようなことができます。

_(data)
    .thru(function(coll) {
        return _.union(coll, _.pluck(coll, 'children'));
    })
    .flatten()
    .find({ id: 4 });

ここでは、ラップされた値を初期化するために thru() が使用されます。元の配列とネストされた子の和集合を返します。この配列構造は flatten() を使用して平坦化されるため、 find() アイテムを使用できます。

31
Adam Boduch

これは非常に単純な tree traversal タスクです。これを解決する最も簡単な方法は再帰です( jsbin へのリンク)。それはどんな深さでも動作します(もちろん再帰の制限があります)。これは最悪の複雑さO(n)を持つ最速の方法の1つです。

function find(id, items) {
  var i = 0, found;

  for (; i < items.length; i++) {
    if (items[i].id === id) {
      return items[i];
    } else if (_.isArray(items[i].children)) {
      found = find(id, items[i].children);
      if (found) {
        return found;
      }
    }
  }
}

更新:

すべての一致を見つける-わずかに変更された関数(上記のjsbinリンクが更新されます):

function findAll(id, items) {
  var i = 0, found, result = [];

  for (; i < items.length; i++) {
    if (items[i].id === id) {
      result.Push(items[i]);
    } else if (_.isArray(items[i].children)) {
      found = findAll(id, items[i].children);
      if (found.length) {
        result = result.concat(found);
      }
    }
  }

  return result;
}
3
Kiril

子キーと無制限の深さを持つ別のlodashオプション。

const flattenItems = (items, key) => {
    return items.reduce((flattenedItems, item) => {
        flattenedItems.Push(item)
        if (Array.isArray(item[key])) {
            flattenedItems = flattenedItems.concat(flattenItems(item[key], key))
        }
        return flattenedItems
    }, [])
}

const item = find(flattenItems(items, 'children'), ['id', 4])
2
Richard Ayotte