【问题标题】:refactoring assistance with reducing some array data objects in JavaScript重构帮助减少 JavaScript 中的一些数组数据对象
【发布时间】:2020-05-28 19:54:56
【问题描述】:

我需要以某种方式减少配置文件数组中的数据,以便最终对象根据最喜欢的电影和喜欢/收藏该电影的用户对配置文件 obj 中的数据进行分组。 我想要类似的东西:

{
 'Forrest Gump': ["Nicholas Lain"],
 'Planet Earth 1': ["Jane Jones", "Matthew Johnson"]
}

来自以下数据对象:

const profiles = [
      {
        id: 1,
        userID: '1',
        favoriteMovieID: '1',
      },
      {
        id: 2,
        userID: '2',
        favoriteMovieID: '1',
      },
      {
        id: 3,
        userID: '4',
        favoriteMovieID: '5',
      }
    ];

    const users = {
      1: {
        id: 1,
        name: 'Jane Cruz',
        userName: 'coder',
      },
      2: {
        id: 2,
        name: 'Matthew Johnson',
        userName: 'mpage',
      }
    };

    const movies = {
      1: {
        id: 1,
        name: 'Planet Earth 1',
      },
      2: {
        id: 2,
        name: 'Selma',
      }
    };

我需要一些想法来重构以下代码,以便它返回到用户和电影对象,以从我在下面捕获的 ID 中获取他们的名字。我需要捕获名称,而不是 ID。

profiles.reduce(function (acc, obj) {
    let key = obj['favoriteMovieID']
    if (!acc[key]) {
      acc[key] = []
    }
    acc[key].push(obj.userID)
    return acc
  }, {})

【问题讨论】:

    标签: javascript arrays object higher-order-functions


    【解决方案1】:

    这是一种技术,对个人资料进行折叠,在参数中获取电影和人物姓名,然后使用该数据简单地编写一个新的累加器。请注意,这存在潜在的性能问题,如 Rich Snapp 的 excellent article 中所述。如果这给您带来了实际问题,那么很容易改变它来改变累加器。

    我添加了一些额外的数据来显示当用户或电影不在适当的列表中时会发生什么。如果这永远不会发生,您可以稍微简化nameperson 声明。但我不建议这样做,因为事实上“永远不会发生”的事情确实经常发生。

    const groupNamesByMovie = (profiles, users, movies) => 
      profiles .reduce ((
        a, {userID, favoriteMovieID}, _, __, 
        {name} = movies [favoriteMovieID] || {name: 'Unknown Movie'},
        {name: person} = users [userID] || {name: 'Unknown Person'}
      ) => ({
        ...a,
        [name]: [... (a [name] || []), person]
      }), {})
    
    const profiles = [{id: 1, userID: "1", favoriteMovieID: "1"}, {id: 2, userID: "2", favoriteMovieID: "1"}, {id: 3, userID: "4", favoriteMovieID: "5"}, {id: 4, userID: "6", favoriteMovieID: "5"}, {id: 5, userID: "5", favoriteMovieID: "7"}]
    const users = {1: {id: 1, name: "Jane Cruz", userName: "coder"}, 2: {id: 2, name: "Matthew Johnson", userName: "mpage"}, 4: {id: 4, name: "Nicholas Lain", userName: "nlain"}, 5: {id: 5, name: "Fred Flintstone", userName: "bedrock1"}}
    const movies = {1: {id: 1, name: 'Planet Earth 1'}, 2: {id: 2, name: 'Selma'}, 5: {id: 5, name: 'Forrest Gump'}}
    
    console .log (
      groupNamesByMovie (profiles, users, movies)
    )

    请注意,参数___ 只是用作占位符,因为我们不关心reduceindexarray 参数。

    更新

    有人要求澄清。为了比较,下面是这个相同想法的更重要的版本:

    const getNamesByMovie = (profiles, users, movies) =>
      profiles .reduce ((acc, {userID, favoriteMovieID}) => {
        const movie = movies [favoriteMovieID]
        const name = movie ? movie.name : 'Unknown Movie'
        const user = users [userID]
        const person = user ? user.name : 'Unknown Person'
        const fans = acc [name] || []
        return {
          ... acc,
          [name]: [... fans, person]
        }
    
      }, {})
    

    如果您想避免潜在的性能问题,您可以将 return 语句替换为如下内容:

        acc [name] = fans
        fans .push (person)
        return acc
    

    其中任何一个都与上面的原件做同样的事情。我选择这种初始样式是因为我不喜欢改变累加器对象,更喜欢总是创建一个新版本……而且因为我更喜欢使用表达式而不是语句。但这种风格确实需要一些时间来适应。

    您还询问了我们如何将其他参数传递给reduce 回调。我们没有。相反,我们定义了一些额外的参数,并根据之前的参数对其进行初始化。

    【讨论】:

    • 如何传递超过 4 个参数来减少回调? {name} 和 {name: person}。我还需要帮助了解 reduce 回调中发生的事情。
    • 添加说明。
    • 我花了几个小时来解压缩加载在压缩代码中的 ES6 好东西(第一种方法)。即对象解构和使用传播来组合数组和对象。现在说得通了。第三种方法(用更传统的方法来解决性能问题)马上就有意义了。非常感谢您,先生!
    【解决方案2】:

    const profiles = [
          {
            id: 1,
            userID: '1',
            favoriteMovieID: '1',
          },
          {
            id: 2,
            userID: '2',
            favoriteMovieID: '1',
          },
          {
            id: 3,
            userID: '4',
            favoriteMovieID: '5',
          }
        ];
    
        const users = {
          1: {
            id: 1,
            name: 'Jane Cruz',
            userName: 'coder',
          },
          2: {
            id: 2,
            name: 'Matthew Johnson',
            userName: 'mpage',
          }
        };
    
        const movies = {
          1: {
            id: 1,
            name: 'Planet Earth 1',
          },
          2: {
            id: 2,
            name: 'Selma',
          }
        };
        
        
     const singleProfileNameFavoriteMovie = profiles.map(profile => `${users[profile.userID].name}'s favorite movie is  ${movies[profile.favoriteMovieID].name}` )
        

    const profiles = [
      {
        id: 1,
        userID: '1',
        favoriteMovieID: '1',
      },
      {
        id: 2,
        userID: '2',
        favoriteMovieID: '1',
      },
      {
        id: 3,
        userID: '4',
        favoriteMovieID: '5',
      },
      {
        id: 4,
        userID: '5',
        favoriteMovieID: '2',
      },
      {
        id: 5,
        userID: '3',
        favoriteMovieID: '5',
      },
      {
        id: 6,
        userID: '6',
        favoriteMovieID: '4',
      },
    ];
    
    const users = {
      1: {
        id: 1,
        name: 'Jane Cruz',
        userName: 'coder',
      },
      2: {
        id: 2,
        name: 'Matthew Johnson',
        userName: 'mpage',
      },
      3: {
        id: 3,
        name: 'Autumn Green',
        userName: 'user123',
      },
      4: {
        id: 4,
        name: 'John Doe',
        userName: 'user123',
      },
      5: {
        id: 5,
        name: 'Lauren Carlson',
        userName: 'user123',
      },
      6: {
        id: 6,
        name: 'Nicholas Lain',
        userName: 'user123',
      },
    };
    
    const movies = {
      1: {
        id: 1,
        name: 'Planet Earth 1',
      },
      2: {
        id: 2,
        name: 'Selma',
      },
      3: {
        id: 3,
        name: 'Million Dollar Baby',
      },
      4: {
        id: 4,
        name: 'Forrest Gump',
      },
      5: {
        id: 5,
        name: 'Get Out',
      },
    };
    
    const singleProfileFavoriteMovie = profiles.map(profile => `${users[profile.userID].name}'s favorite movie is  ${movies[profile.favoriteMovieID].name}` );
    
    console.log(singleProfileFavoriteMovie);

    【讨论】:

      猜你喜欢
      • 2018-09-25
      • 1970-01-01
      • 2021-03-10
      • 2018-09-01
      • 1970-01-01
      • 2021-04-02
      • 2019-01-26
      • 1970-01-01
      相关资源
      最近更新 更多