在另一个Array内的Array中查找Object

时间:2018-05-16 23:49:06

标签: javascript arrays object functional-programming

let bigArray = [
{
    Name: 'Trump',
    children: [
                 {Name: 'TrumpChild1', City: 'city1'}, 
                 {Name: 'TrumpChild2', City: 'city2'}
    ]
},
{
    Name: 'Barack Obama',
    children: [
                 {Name: 'Barack Obama Child1', City: 'city3'}, 
                 {Name: 'Barack Obama Child2', City: 'city4'}
    ]
},
{
    Name: 'Clinton',
    children: [
                 {Name: 'Clinton Child 1', City: 'city5'}, 
                 {Name: 'Clinton Child2', City: 'city6'}
    ]
},

我想从另一个数组中的数组中找到一个对象

bigArray.find(b => b.children.find(c=>c.City === 'city1'))

上面的代码返回ARRAY父亲

bigArray.forEach(b => b.children.find(c=>c.City === 'city1'))

并返回undefined

返回所需对象的最佳方法是什么?

4 个答案:

答案 0 :(得分:3)

您可以先将此数组展开为内部对象数组,然后使用filter()find()



let bigArray = [
  {
      Name: 'Trump',
      children: [
                   {Name: 'TrumpChild1', City: 'city1'}, 
                   {Name: 'TrumpChild2', City: 'city2'}
      ]
  },
  {
      Name: 'Barack Obama',
      children: [
                   {Name: 'Barack Obama Child1', City: 'city3'}, 
                   {Name: 'Barack Obama Child2', City: 'city4'}
      ]
  },
  {
      Name: 'Clinton',
      children: [
                   {Name: 'Clinton Child 1', City: 'city5'}, 
                   {Name: 'Clinton Child2', City: 'city6'}
      ]
  }
];

let all = bigArray.reduce((prev, next) => prev.concat(next.children), []);
let result = all.find(obj => obj.City === 'city1');
console.log(result);

// if there can be multiple matches then use filter
let results = all.filter(obj => obj.City === 'city1');
console.log(results);




答案 1 :(得分:1)

孩子可能出生在同一个城市,因此find()并不是特别适合这个问题,因为它只返回它寻找的第一个结果。在这种情况下,filter()是我们需要的功能。

下面,我们致电reduce()的内的filter 。这与其他答案不同,因为它不会多次迭代您的输入数据。另一个答案将首先创建一个完整的子项阵列,然后在第二次迭代中,选择与您的城市查询匹配的子项。

或者,这个答案通过每个总统一次迭代,并在整个过程中将任何匹配的孩子添加到结果中。

const findByCity = (city, data = {}) =>
  data .reduce
    ( (result, { children = [] }) =>
        result .concat (children .filter (c => c.city === city))
    , []
    )

在您的输入数据中,每个孩子都有一个独特的城市,所以它不会产生良好的示范。我添加了一些在city5出生的孩子,所以我们可以看到一个包含多个孩子的答案

const data =
  [ { name: 'Trump'
    , children:
        [ { name: 'Trump Child 1', city: 'city1' }
        , { name: 'Trump Child 2', city: 'city2' }
        ]
    }
  , { name: 'Barack Obama'
    , children:
        [ { name: 'Barack Obama Child 1', city: 'city3' }
        , { name: 'Barack Obama Child 2', city: 'city4' }
        ]
    }
  , { name: 'Clinton'
    , children:
        [ { name: 'Clinton Child 1', city: 'city5' }
        , { name: 'Clinton Child 2', city: 'city6' }
        ]
    }
  , { name: 'Bush'
    , children:
        [ { name: 'Bush Child 1', city: 'city5' }
        , { name: 'Bush Child 2', city: 'city5' }
        ]
    }
  ]

console .log (findByCity ('city1', data))
// [ { name: 'Trump Child 1', city: 'city1' } ]

console .log (findByCity ('city5', data))
// [ { name: 'Clinton Child 1', city: 'city5' }
// , { name: 'Bush Child 1', city: 'city5' }
// , { name: 'Bush Child 2', city: 'city5' }
// ]

如果您的数据包含children - 更少的总统,此处提供的另一个答案将会中断。 findByCity不会遇到此问题

const data =
  [ // ...
  , { name: 'Bush'
    , children:
        [ { name: 'Bush Child 1', city: 'city5' }
        , { name: 'Bush Child 2', city: 'city5' }
        ]
    }

  // watch out for child-less presidents!
  , { name: 'Polk' }
  ]

展开以下程序,在浏览器中运行

const findByCity = (city, data = {}) =>
  data .reduce
    ( (result, { children = [] }) =>
        result .concat (children .filter (c => c.city === city))
    , []
    )

const data =
  [ { name: 'Trump'
    , children:
        [ { name: 'Trump Child 1', city: 'city1' }
        , { name: 'Trump Child 2', city: 'city2' }
        ]
    }
  , { name: 'Barack Obama'
    , children:
        [ { name: 'Barack Obama Child 1', city: 'city3' }
        , { name: 'Barack Obama Child 2', city: 'city4' }
        ]
    }
  , { name: 'Clinton'
    , children:
        [ { name: 'Clinton Child 1', city: 'city5' }
        , { name: 'Clinton Child 2', city: 'city6' }
        ]
    }
  , { name: 'Bush'
    , children:
        [ { name: 'Bush Child 1', city: 'city5' }
        , { name: 'Bush Child 2', city: 'city5' }
        ]
    }
  , { name: 'Polk' }
  ]

console .log (findByCity ('city1', data))
// [ { name: 'Trump Child 1', city: 'city1' } ]
    
console .log (findByCity ('city5', data))
// [ { name: 'Clinton Child 1', city: 'city5' }
// , { name: 'Bush Child 1', city: 'city5' }
// , { name: 'Bush Child 2', city: 'city5' }
// ]

答案 2 :(得分:0)

您也可以在不展平阵列的情况下执行此操作。

let matches = [];

// using array.forEach(), plus && in .map() to shorten the comparison syntax
bigArray.forEach(obj => {obj.children.map(c => c.City == 'city1' &&  matches.push(c))});

// and this version works even if there is not a `children` property
bigArray.forEach(obj => {obj.children && obj.children.map(c => c.City == 'city1' &&  matches.push(c))});

答案 3 :(得分:0)

我遇到了与这里几乎相同的问题,但对我而言,在这种情况下,我正在寻找元素的整体名称,即父亲的名字(例如姓名:“特朗普”) 我只是使用了双重查找来使其尽可能简单和高效^^ 我的代码:

let bigArray = [
  {
      Name: 'Trump',
      children: [
                   {Name: 'TrumpChild1', City: 'city1'}, 
                   {Name: 'TrumpChild2', City: 'city2'}
      ]
  },
  {
      Name: 'Barack Obama',
      children: [
                   {Name: 'Barack Obama Child1', City: 'city3'}, 
                   {Name: 'Barack Obama Child2', City: 'city4'}
      ]
  },
  {
      Name: 'Clinton',
      children: [
                   {Name: 'Clinton Child 1', City: 'city5'}, 
                   {Name: 'Clinton Child2', City: 'city6'}
      ]
  }
];

const element = bigArray.find((el) => el.children.find((item) => item.City === 'city2'))
const {Name: fatherName} = element
// for the element
console.log(element)
// for the father name 
console.log(fatherName)

如果您只需要名称,您可以删除元素并使用 {Name:fatherName} 更改它