【问题标题】:What would be the most efficient way to find an object in an array of objects with distinct value which is an array?在具有不同值的对象数组中查找对象的最有效方法是什么?
【发布时间】:2020-04-15 05:16:18
【问题描述】:

我最初在几个月前的一次采访中遇到了这个问题,现在已经开始解决了。

所以我们有了这个对象数组,目标是找到一个对象,其中的演员在电影中没有出现过一次以上。所以基本上找一部有独特演员的电影。

[
  {
    name: 'The Dark Knight',
    rating: 'PG-13',
    year: 2012,
    bestScene: {
      name: 'fight',
      location: 'sewer',
      sceneLength: 10,
      actors: ['Christian Bale', 'Tom Hardy']
    }
  },
  {
    name: 'Good Burger',
    rating: 'PG',
    year: 1994,
    bestScene: {
      name: 'jump',
      location: 'giant milkshake',
      sceneLength: 5,
      actors: ['Kenan Thompson', 'Kel Mitchell']
    }
  },
  {
    name: 'Sharknado 2: The Second One',
    rating: 'TV-14',
    year: 2013
  },
  {
    name: 'The Big Short',
    rating: 'R',
    year: 2015,
    bestScene: {
      name: 'explanation',
      location: 'casino',
      sceneLength: 20,
      actors: ['Christian Bale', 'Steve Carrell']
    }
  }
]

我为自己设定的目标是使用函数式方法来解决它,因此我们自然需要像这样清除不存在 bestScene 的对象:

const moviesWithActorsPresent = movies.filter((movie) => movie.bestScene)

然后我可以使用reduce 构造一个对象数组,如下所示:

[
  { 'The Dark Knight': [ 'Christian Bale', 'Tom Hardy' ] },
  { 'Good Burger': [ 'Kenan Thompson', 'Kel Mitchell' ] },
  { 'The Big Short': [ 'Christian Bale', 'Steve Carrell' ] }
]

然后循环使用forforEach 并在一个临时变量中跟踪演员,但对我来说这并不是一个优雅的解决方案。

我们可以在这里使用什么 CS 概念来有效地解决它?

【问题讨论】:

    标签: javascript arrays functional-programming computer-science


    【解决方案1】:

    获得moviesWithActorsPresent 后,创建一个对象(或映射),计算整个数组中每个参与者的出现次数。然后你可以.find 一个对象,.every actor 的计数正好为 1:

    const movies =[
      {
        name: 'The Dark Knight',
        rating: 'PG-13',
        year: 2012,
        bestScene: {
          name: 'fight',
          location: 'sewer',
          sceneLength: 10,
          actors: ['Christian Bale', 'Tom Hardy']
        }
      },
      {
        name: 'Good Burger',
        rating: 'PG',
        year: 1994,
        bestScene: {
          name: 'jump',
          location: 'giant milkshake',
          sceneLength: 5,
          actors: ['Kenan Thompson', 'Kel Mitchell']
        }
      },
      {
        name: 'Sharknado 2: The Second One',
        rating: 'TV-14',
        year: 2013
      },
      {
        name: 'The Big Short',
        rating: 'R',
        year: 2015,
        bestScene: {
          name: 'explanation',
          location: 'casino',
          sceneLength: 20,
          actors: ['Christian Bale', 'Steve Carrell']
        }
      }
    ];
    const moviesWithActorsPresent = movies.filter((movie) => movie.bestScene)
    const actorCounts = moviesWithActorsPresent.reduce((a, { bestScene }) => {
      const { actors } = bestScene;
      return Object.assign(
        {}, // don't mutate
        a, // prior counts
        ...actors.map(actor => ({ [actor]: (a[actor] || 0) + 1 }))
      );
    }, {});
    const movieWithUniqueActors = moviesWithActorsPresent.find(({ bestScene }) => (
      bestScene.actors.every(actor => actorCounts[actor] === 1)
    ));
    console.log(movieWithUniqueActors);

    几乎可以肯定这无关紧要,但如果需要,您可以将.filter 功能放入.reduce

    const movies = [{
        name: 'The Dark Knight',
        rating: 'PG-13',
        year: 2012,
        bestScene: {
          name: 'fight',
          location: 'sewer',
          sceneLength: 10,
          actors: ['Christian Bale', 'Tom Hardy']
        }
      },
      {
        name: 'Good Burger',
        rating: 'PG',
        year: 1994,
        bestScene: {
          name: 'jump',
          location: 'giant milkshake',
          sceneLength: 5,
          actors: ['Kenan Thompson', 'Kel Mitchell']
        }
      },
      {
        name: 'Sharknado 2: The Second One',
        rating: 'TV-14',
        year: 2013
      },
      {
        name: 'The Big Short',
        rating: 'R',
        year: 2015,
        bestScene: {
          name: 'explanation',
          location: 'casino',
          sceneLength: 20,
          actors: ['Christian Bale', 'Steve Carrell']
        }
      }
    ];
    const actorCounts = movies.reduce((a, { bestScene }) => {
      if (!bestScene) {
        return a;
      }
      const { actors } = bestScene;
      return Object.assign({}, // don't mutate
        a, // prior counts
        ...actors.map(actor => ({
          [actor]: (a[actor] || 0) + 1
        }))
      );
    }, {});
    const movieWithUniqueActors = movies.find(({ bestScene }) => (
      bestScene.actors.every(actor => actorCounts[actor] === 1)
    ));
    console.log(movieWithUniqueActors);

    【讨论】:

    • 我想我对every 的解决方案和 TIL 过于复杂了。
    • 使用 filter 然后 reduce 循环遍历数组两次可能比在回调中对 bestScene 执行 reduce 和过滤效率低。
    【解决方案2】:

    您只需要创建一个将films by actors 分组的函数,然后只取那些有1 电影的函数。

    const group = (data) => data
      .reduce((res, { name, bestScene }) => {
        ((bestScene || {}).actors || []).forEach(actor => {
          
          res[actor] = (res[actor] || []).concat(name);
        });
        
        return res;
      }, {});
    
    const solve = data => Object
      .entries(group(data))
      .filter(([author, films]) => films.length === 1)
    
    const data = [
      {
        name: 'The Dark Knight',
        rating: 'PG-13',
        year: 2012,
        bestScene: {
          name: 'fight',
          location: 'sewer',
          sceneLength: 10,
          actors: ['Christian Bale', 'Tom Hardy']
        }
      },
      {
        name: 'Good Burger',
        rating: 'PG',
        year: 1994,
        bestScene: {
          name: 'jump',
          location: 'giant milkshake',
          sceneLength: 5,
          actors: ['Kenan Thompson', 'Kel Mitchell']
        }
      },
      {
        name: 'Sharknado 2: The Second One',
        rating: 'TV-14',
        year: 2013
      },
      {
        name: 'The Big Short',
        rating: 'R',
        year: 2015,
        bestScene: {
          name: 'explanation',
          location: 'casino',
          sceneLength: 20,
          actors: ['Christian Bale', 'Steve Carrell']
        }
      }
    ];
    
    console.log(solve(data));

    【讨论】:

      猜你喜欢
      • 2018-09-24
      • 2020-02-11
      • 2021-12-06
      • 1970-01-01
      • 2014-05-07
      • 2019-12-17
      • 2020-06-27
      • 2019-12-16
      • 2014-12-04
      相关资源
      最近更新 更多