代码之家  ›  专栏  ›  技术社区  ›  BARNOWL

如何使用reduce从深度嵌套数组对象中检索值

  •  0
  • BARNOWL  · 技术社区  · 4 年前

    我正在尝试获取所有用户的列表 author.username 财产。这意味着访问帖子作者、评论作者和评论回复作者。我希望返回一个包含用户名列表的数组。

    预期产量

    ["blankman", "blankman2", "barnowl", "barnowl2", "blankman3"]
    

    错误的输出

    ["blankman", "blankman2blankman3", "barnowl2"]
    

    我就是这样做的,但我认为我做错了。因为它不是动态的

    const arr = [{
      "id": 5,
      "title": "buttercup",
      "postContent": "dsdsfsfsfsfsfs",
      "likedByMe": false,
      "likeCounts": 0,
      "userId": 1,
      "createdAt": "2020-08-17T03:41:16.749Z",
      "updatedAt": "2020-08-17T03:41:16.749Z",
      "author": {
        "username": "blankman",
        "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
        "bio": null
      },
      "Likes": [],
      "Comments": [{
          "id": 46,
          "comment_body": "fsfsfsfsfsf",
          "gifUrl": "",
          "userId": 1,
          "postId": 5,
          "createdAt": "2020-08-18T04:46:08.946Z",
          "updatedAt": "2020-08-18T04:46:08.946Z",
          "commentReplies": [{
            "id": 18,
            "replyBody": "fsfsffsffsffsf",
            "userId": 2,
            "commentId": 46,
            "postId": 5,
            "createdAt": "2020-08-21T16:40:47.205Z",
            "updatedAt": "2020-08-21T16:40:47.205Z",
            "author": {
              "username": "barnowl",
              "gravatar": null,
              "bio": null
            }
          }],
          "author": {
            "username": "blankman2",
            "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
            "bio": null
          }
        },
        {
          "id": 47,
          "comment_body": "fsfsfsfsfsf",
          "gifUrl": "",
          "userId": 1,
          "postId": 5,
          "createdAt": "2020-08-18T04:46:08.946Z",
          "updatedAt": "2020-08-18T04:46:08.946Z",
          "commentReplies": [{
            "id": 18,
            "replyBody": "fsfsffsffsffsf",
            "userId": 2,
            "commentId": 46,
            "postId": 5,
            "createdAt": "2020-08-21T16:40:47.205Z",
            "updatedAt": "2020-08-21T16:40:47.205Z",
            "author": {
              "username": "barnowl2",
              "gravatar": null,
              "bio": null
            }
          }],
          "author": {
            "username": "blankman3",
            "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
            "bio": null
          }
        },
    
      ],
      "RePosts": [],
      "RepostedByMe": false
    }]
    
    const findUsers = arr.reduce((acc, cv) => {
      const users = [
        ...acc,
        cv.author.username, // get first level author.username
        cv.Comments.reduce((acc, cv) => acc.concat(cv.author.username), ""), // get comments author.username 
        cv.Comments.reduce((acc, cv) => cv.commentReplies.reduce((acc, cv) => acc.concat(cv.author.username), ""), "") // get comment replies author.username
    
      ]
      return users
    }, [])
    console.log(findUsers)
    0 回复  |  直到 4 年前
        1
  •  3
  •   PotatoParser    4 年前

    您可以迭代或递归地执行此操作:

    const arr = [{
      "id": 5,
      "title": "buttercup",
      "postContent": "dsdsfsfsfsfsfs",
      "likedByMe": false,
      "likeCounts": 0,
      "userId": 1,
      "createdAt": "2020-08-17T03:41:16.749Z",
      "updatedAt": "2020-08-17T03:41:16.749Z",
      "author": {
        "username": "blankman",
        "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
        "bio": null
      },
      "Likes": [],
      "Comments": [
        {
          "id": 46,
          "comment_body": "fsfsfsfsfsf",
          "gifUrl": "",
          "userId": 1,
          "postId": 5,
          "createdAt": "2020-08-18T04:46:08.946Z",
          "updatedAt": "2020-08-18T04:46:08.946Z",
          "commentReplies": [
            {
              "id": 18,
              "replyBody": "fsfsffsffsffsf",
              "userId": 2,
              "commentId": 46,
              "postId": 5,
              "createdAt": "2020-08-21T16:40:47.205Z",
              "updatedAt": "2020-08-21T16:40:47.205Z",
              "author": {
                "username": "barnowl",
                "gravatar": null,
                "bio": null
              }
            }
          ],
          "author": {
            "username": "blankman2",
            "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
            "bio": null
          }
        },
         {
          "id": 47,
          "comment_body": "fsfsfsfsfsf",
          "gifUrl": "",
          "userId": 1,
          "postId": 5,
          "createdAt": "2020-08-18T04:46:08.946Z",
          "updatedAt": "2020-08-18T04:46:08.946Z",
          "commentReplies": [
            {
              "id": 18,
              "replyBody": "fsfsffsffsffsf",
              "userId": 2,
              "commentId": 46,
              "postId": 5,
              "createdAt": "2020-08-21T16:40:47.205Z",
              "updatedAt": "2020-08-21T16:40:47.205Z",
              "author": {
                "username": "barnowl2",
                "gravatar": null,
                "bio": null
              }
            }
          ],
          "author": {
            "username": "blankman3",
            "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
            "bio": null
          }
        },
        
      ],
      "RePosts": [],
      "RepostedByMe": false
    }]
    
    // No recursion
    function getUsers(array) {
      return array.flatMap(v => {
        let comments = v.Comments;
        return [v.author.username].concat(comments.flatMap(c => {
          let replies = c.commentReplies;
          return [c.author.username].concat(replies.flatMap(r => {
            return r.author.username;
          }));
        }));
      });
    }
    
    // Recursion
    function recursGetUsers(array) {
      if (!array) return [];
      return array.flatMap(v => {
        return [v.author.username]
        .concat(recursGetUsers(v.Comments))
        .concat(recursGetUsers(v.commentReplies));
      });
    }
    
    console.log(getUsers(arr));
    
    console.log(recursGetUsers(arr));
        2
  •  2
  •   Unmitigated    4 年前

    您可以使用多个嵌套 flatMap map 操作。

    const arr = [{ "id": 5, "title": "buttercup", "postContent": "dsdsfsfsfsfsfs", "likedByMe": false, "likeCounts": 0, "userId": 1, "createdAt": "2020-08-17T03:41:16.749Z", "updatedAt": "2020-08-17T03:41:16.749Z", "author": { "username": "blankman", "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", "bio": null }, "Likes": [], "Comments": [{ "id": 46, "comment_body": "fsfsfsfsfsf", "gifUrl": "", "userId": 1, "postId": 5, "createdAt": "2020-08-18T04:46:08.946Z", "updatedAt": "2020-08-18T04:46:08.946Z", "commentReplies": [{ "id": 18, "replyBody": "fsfsffsffsffsf", "userId": 2, "commentId": 46, "postId": 5, "createdAt": "2020-08-21T16:40:47.205Z", "updatedAt": "2020-08-21T16:40:47.205Z", "author": { "username": "barnowl", "gravatar": null, "bio": null } }], "author": { "username": "blankman2", "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", "bio": null } }, { "id": 47, "comment_body": "fsfsfsfsfsf", "gifUrl": "", "userId": 1, "postId": 5, "createdAt": "2020-08-18T04:46:08.946Z", "updatedAt": "2020-08-18T04:46:08.946Z", "commentReplies": [{ "id": 18, "replyBody": "fsfsffsffsffsf", "userId": 2, "commentId": 46, "postId": 5, "createdAt": "2020-08-21T16:40:47.205Z", "updatedAt": "2020-08-21T16:40:47.205Z", "author": { "username": "barnowl2", "gravatar": null, "bio": null } }], "author": { "username": "blankman3", "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", "bio": null } }, ], "RePosts": [], "RepostedByMe": false }];
    const res = arr.flatMap(x => [x.author.username].concat(x.Comments.flatMap(y => y.commentReplies.map(z => z.author.username).concat(y.author.username))));
    console.log(res);
        3
  •  1
  •   Sphinx    4 年前

    如果你的模式已经确定,你的方法就是一个解决方案,几乎达到了目标(尽管 递归 是另一种解决方案)。代码中的问题是使用 Array.concat 然后返回 String 你应该退一个 [] 与最外层的减少相同。

    请查看以下代码片段:

    const arr = [{
      "id": 5,
      "title": "buttercup",
      "postContent": "dsdsfsfsfsfsfs",
      "likedByMe": false,
      "likeCounts": 0,
      "userId": 1,
      "createdAt": "2020-08-17T03:41:16.749Z",
      "updatedAt": "2020-08-17T03:41:16.749Z",
      "author": {
        "username": "blankman",
        "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
        "bio": null
      },
      "Likes": [],
      "Comments": [
        {
          "id": 46,
          "comment_body": "fsfsfsfsfsf",
          "gifUrl": "",
          "userId": 1,
          "postId": 5,
          "createdAt": "2020-08-18T04:46:08.946Z",
          "updatedAt": "2020-08-18T04:46:08.946Z",
          "commentReplies": [
            {
              "id": 18,
              "replyBody": "fsfsffsffsffsf",
              "userId": 2,
              "commentId": 46,
              "postId": 5,
              "createdAt": "2020-08-21T16:40:47.205Z",
              "updatedAt": "2020-08-21T16:40:47.205Z",
              "author": {
                "username": "barnowl",
                "gravatar": null,
                "bio": null
              }
            }
          ],
          "author": {
            "username": "blankman2",
            "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
            "bio": null
          }
        },
         {
          "id": 47,
          "comment_body": "fsfsfsfsfsf",
          "gifUrl": "",
          "userId": 1,
          "postId": 5,
          "createdAt": "2020-08-18T04:46:08.946Z",
          "updatedAt": "2020-08-18T04:46:08.946Z",
          "commentReplies": [
            {
              "id": 18,
              "replyBody": "fsfsffsffsffsf",
              "userId": 2,
              "commentId": 46,
              "postId": 5,
              "createdAt": "2020-08-21T16:40:47.205Z",
              "updatedAt": "2020-08-21T16:40:47.205Z",
              "author": {
                "username": "barnowl2",
                "gravatar": null,
                "bio": null
              }
            }
          ],
          "author": {
            "username": "blankman3",
            "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
            "bio": null
          }
        },
        
      ],
      "RePosts": [],
      "RepostedByMe": false
    }]
    
    const findUsers = arr.reduce((acc, cv) => {
      const users = [
        ...acc,
        cv.author.username, // get first level author.username
        ...cv.Comments.reduce((acc, cv) => [...acc, cv.author.username], []), // get comments author.username 
        ...cv.Comments.reduce((acc, cv) => [...acc, ...cv.commentReplies.reduce((acc, cv) => [...acc, cv.author.username], [])], []) // get comment replies author.username
    
      ]
      return users
    }, [])
    
    console.log(findUsers)
        4
  •  1
  •   GirkovArpa    4 年前

    这是对象的模式:

    • author.username
    • Comments[i].author.username
    • Comments[i].commentReplies[i].author.username

    你特别要求使用 .reduce 所以这里有一个解决方案,使用 .减少 伴随着大量的破坏:

    const usernames = arr.reduce((names, { author: { username }, Comments }) => {
      names.push(username);
      Comments.forEach(({ author: { username }, commentReplies }) => {
        names.push(username);
        commentReplies.forEach(({ author: { username } }) => names.push(username));
      });
      return names;
    }, []);
    

    实例:

    'use strict';
    
    const arr = [
      {
        "id": 5,
        "title": "buttercup",
        "postContent": "dsdsfsfsfsfsfs",
        "likedByMe": false,
        "likeCounts": 0,
        "userId": 1,
        "createdAt": "2020-08-17T03:41:16.749Z",
        "updatedAt": "2020-08-17T03:41:16.749Z",
        "author": {
          "username": "blankman",
          "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
          "bio": null
        },
        "Likes": [],
        "Comments": [{
          "id": 46,
          "comment_body": "fsfsfsfsfsf",
          "gifUrl": "",
          "userId": 1,
          "postId": 5,
          "createdAt": "2020-08-18T04:46:08.946Z",
          "updatedAt": "2020-08-18T04:46:08.946Z",
          "commentReplies": [{
            "id": 18,
            "replyBody": "fsfsffsffsffsf",
            "userId": 2,
            "commentId": 46,
            "postId": 5,
            "createdAt": "2020-08-21T16:40:47.205Z",
            "updatedAt": "2020-08-21T16:40:47.205Z",
            "author": {
              "username": "barnowl",
              "gravatar": null,
              "bio": null
            }
          }],
          "author": {
            "username": "blankman2",
            "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
            "bio": null
          }
        },
        {
          "id": 47,
          "comment_body": "fsfsfsfsfsf",
          "gifUrl": "",
          "userId": 1,
          "postId": 5,
          "createdAt": "2020-08-18T04:46:08.946Z",
          "updatedAt": "2020-08-18T04:46:08.946Z",
          "commentReplies": [{
            "id": 18,
            "replyBody": "fsfsffsffsffsf",
            "userId": 2,
            "commentId": 46,
            "postId": 5,
            "createdAt": "2020-08-21T16:40:47.205Z",
            "updatedAt": "2020-08-21T16:40:47.205Z",
            "author": {
              "username": "barnowl2",
              "gravatar": null,
              "bio": null
            }
          }],
          "author": {
            "username": "blankman3",
            "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
            "bio": null
          }
        },
        ],
        "RePosts": [],
        "RepostedByMe": false
      }
    ];
    
    // author.username
    // Comments[i].author.username
    // Comments[i].commentReplies[i].author.username
    
    const usernames = arr.reduce((names, { author: { username }, Comments }) => {
      names.push(username);
      Comments.forEach(({ author: { username }, commentReplies }) => {
        names.push(username);
        commentReplies.forEach(({ author: { username } }) => names.push(username));
      });
      return names;
    }, []);
    
    console.log(usernames);
    // => [ 'blankman', 'blankman2', 'barnowl', 'blankman3', 'barnowl2' ]
        5
  •  1
  •   trincot Jakube    4 年前

    你需要一个递归函数。与 flatMap 您可以确保递归返回的数组被组合成一个平面数组。

    这里有一个可能的实现,它不依赖于“Comments”和“commentReplies”等属性名,而只是扫描所有数组:

    const collect = arr => Array.isArray(arr) ? arr.flatMap(value => 
        [value.author?.username].concat(Object.values(value).flatMap(collect))
    ).filter(Boolean) : [];
    
    // demo
    const arr = [{"id": 5,"title": "buttercup","postContent": "dsdsfsfsfsfsfs","likedByMe": false,"likeCounts": 0,"userId": 1,"createdAt": "2020-08-17T03:41:16.749Z","updatedAt": "2020-08-17T03:41:16.749Z","author": {"username": "blankman","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null},"Likes": [],"Comments": [{"id": 46,"comment_body": "fsfsfsfsfsf","gifUrl": "","userId": 1,"postId": 5,"createdAt": "2020-08-18T04:46:08.946Z","updatedAt": "2020-08-18T04:46:08.946Z","commentReplies": [{"id": 18,"replyBody": "fsfsffsffsffsf","userId": 2,"commentId": 46,"postId": 5,"createdAt": "2020-08-21T16:40:47.205Z","updatedAt": "2020-08-21T16:40:47.205Z","author": {"username": "barnowl","gravatar": null,"bio": null}}],"author": {"username": "blankman2","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null}},{"id": 47,"comment_body": "fsfsfsfsfsf","gifUrl": "","userId": 1,"postId": 5,"createdAt": "2020-08-18T04:46:08.946Z","updatedAt": "2020-08-18T04:46:08.946Z","commentReplies": [{"id": 18,"replyBody": "fsfsffsffsffsf","userId": 2,"commentId": 46,"postId": 5,"createdAt": "2020-08-21T16:40:47.205Z","updatedAt": "2020-08-21T16:40:47.205Z","author": {"username": "barnowl2","gravatar": null,"bio": null}}],"author": {"username": "blankman3","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null}},],"RePosts": [],"RepostedByMe": false}];
    console.log(collect(arr));

    如果你发现这个函数表达式语法令人困惑,那么这里有一些更详细的类似内容:

    function collect(arr) {
        if (!Array.isArray(arr)) return [];
        let result = [];
        for (let obj of arr) {
            result.push(obj.author?.username);
            for (let key in obj) {
                result = result.concat(collect(obj[key]));
            }
        }
        return result.filter(Boolean); // exclude null/undefined values
    }
    // demo
    const arr = [{"id": 5,"title": "buttercup","postContent": "dsdsfsfsfsfsfs","likedByMe": false,"likeCounts": 0,"userId": 1,"createdAt": "2020-08-17T03:41:16.749Z","updatedAt": "2020-08-17T03:41:16.749Z","author": {"username": "blankman","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null},"Likes": [],"Comments": [{"id": 46,"comment_body": "fsfsfsfsfsf","gifUrl": "","userId": 1,"postId": 5,"createdAt": "2020-08-18T04:46:08.946Z","updatedAt": "2020-08-18T04:46:08.946Z","commentReplies": [{"id": 18,"replyBody": "fsfsffsffsffsf","userId": 2,"commentId": 46,"postId": 5,"createdAt": "2020-08-21T16:40:47.205Z","updatedAt": "2020-08-21T16:40:47.205Z","author": {"username": "barnowl","gravatar": null,"bio": null}}],"author": {"username": "blankman2","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null}},{"id": 47,"comment_body": "fsfsfsfsfsf","gifUrl": "","userId": 1,"postId": 5,"createdAt": "2020-08-18T04:46:08.946Z","updatedAt": "2020-08-18T04:46:08.946Z","commentReplies": [{"id": 18,"replyBody": "fsfsffsffsffsf","userId": 2,"commentId": 46,"postId": 5,"createdAt": "2020-08-21T16:40:47.205Z","updatedAt": "2020-08-21T16:40:47.205Z","author": {"username": "barnowl2","gravatar": null,"bio": null}}],"author": {"username": "blankman3","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null}},],"RePosts": [],"RepostedByMe": false}];
    console.log(collect(arr));
        6
  •  1
  •   Nina Scholz    4 年前

    您可以通过传递父对象的键来进行递归。

    它分为三个步骤,

    1. 检查所移交的值是否是数组,如果不是,则返回空数组,
    2. 检查父密钥是否为 author 如果财产 username 存在,然后取 用户名 财产。
    3. 获取对象的条目,并通过传递父密钥递归获取所有用户名。

    const
        getUsernames = (object, parent) => {
            if (!object || typeof object !== 'object') return [];
            const temp = [];
            if (parent === 'author' && 'username' in object) temp.push(object.username);
            return [
                ...temp,
                ...Object.entries(object).flatMap(([k, v]) => getUsernames(v, k))
            ];
        },
        data = [{ id: 5, title: "buttercup", postContent: "dsdsfsfsfsfsfs", likedByMe: false, likeCounts: 0, userId: 1, createdAt: "2020-08-17T03:41:16.749Z", updatedAt: "2020-08-17T03:41:16.749Z", author: { username: "blankman", gravatar: "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", bio: null }, Likes: [], Comments: [{ id: 46, comment_body: "fsfsfsfsfsf", gifUrl: "", userId: 1, postId: 5, createdAt: "2020-08-18T04:46:08.946Z", updatedAt: "2020-08-18T04:46:08.946Z", commentReplies: [{ id: 18, replyBody: "fsfsffsffsffsf", userId: 2, commentId: 46, postId: 5, createdAt: "2020-08-21T16:40:47.205Z", updatedAt: "2020-08-21T16:40:47.205Z", author: { username: "barnowl", gravatar: null, bio: null } }], author: { username: "blankman2", gravatar: "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", bio: null } }, { id: 47, comment_body: "fsfsfsfsfsf", gifUrl: "", userId: 1, postId: 5, createdAt: "2020-08-18T04:46:08.946Z", updatedAt: "2020-08-18T04:46:08.946Z", commentReplies: [{ id: 18, replyBody: "fsfsffsffsffsf", userId: 2, commentId: 46, postId: 5, createdAt: "2020-08-21T16:40:47.205Z", updatedAt: "2020-08-21T16:40:47.205Z", author: { username: "barnowl2", gravatar: null, bio: null } }], author: { username: "blankman3", gravatar: "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", bio: null } }], RePosts: [], RepostedByMe: false }],
        result = getUsernames(data);
    
    console.log(result);