【问题标题】:How to filter normalized nested JSON data with no array?如何在没有数组的情况下过滤规范化嵌套的 JSON 数据?
【发布时间】:2018-01-06 02:09:57
【问题描述】:

使用 normalizr 库后,我的应用程序的 Redux 状态中有以下标准化 JSON 对象结果:

  { 
    sports: {
        byId: {
          1: {
            id: 1,
            name: 'Soccer',
            slug: 'soccer'
          },
          2: {
            id: 2,
            name: 'Basketball',
            slug: 'basketball'
          },
          3: {
            id: 3,
            name: 'American Football',
            slug: 'american-football'
          }
        },
        allIds: [
          '1',
          '2',
          '3'
        ]
      },
      competitions: {
        byId: {
          '1': {
            id: 1,
            name: 'Competition 1',
            short_name: 'Comp 1',
            slug: 'comp-1',
            sport: 1,
            status: {
             is_live: false 
           }
          },
          '2': {
            id: 2,
            name: 'Competition 2',
            short_name: 'Comp 2',
            slug: 'comp-2',
            sport: 1,
            status: {
             is_live: true 
           }
          },
          '3': {
            id: 3,
            name: 'National Basketball League',
            short_name: 'NBA',
            slug: 'national-basketball-league',
            sport_slug: 'basketball',
            sport: 3,
            status: {
             is_live: true 
           }
          }
        },
        allIds: [
          '1',
          '2',
          '3'
        ]
     }

我想要实现的目标:我想要一个由sports 过滤/分类的competitions 列表。

我该怎么做?

我还希望能够将competitions 分组为status.is_live

那么我怎样才能得到sportcompetitions 细分列表,status.is_live 等于 true,competitions status.is_live 等于 false?

任何帮助表示赞赏!谢谢

【问题讨论】:

    标签: javascript json redux normalizr


    【解决方案1】:

    如果你不想使用lodash,你可以很容易地编写一个.groupBy 函数(example)。您需要遍历输出对象并使用 for 重新分配其子值,而不是使用 .mapValues

    我在示例中使用了 lodash,只是为了指出逻辑。

    注意:我会删除原始响应中数据中的分组,并让客户端自行执行此操作 - 处理未排序的数组和过滤/映射会更容易处理来自具有冗余键的对象的值(因为它们按 Id 表示组)

    let data = {
      sports: {
        byId: {
          1: {
            id: 1,
            name: 'Soccer',
            slug: 'soccer'
          },
          2: {
            id: 2,
            name: 'Basketball',
            slug: 'basketball'
          },
          3: {
            id: 3,
            name: 'American Football',
            slug: 'american-football'
          }
        },
        allIds: [
          '1',
          '2',
          '3'
        ]
      },
      competitions: {
        byId: {
          '1': {
            id: 1,
            name: 'Competition 1',
            short_name: 'Comp 1',
            slug: 'comp-1',
            sport: 1,
            status: {
              is_live: false
            }
          },
          '2': {
            id: 2,
            name: 'Competition 2',
            short_name: 'Comp 2',
            slug: 'comp-2',
            sport: 1,
            status: {
              is_live: true
            }
          },
          '3': {
            id: 3,
            name: 'National Basketball League',
            short_name: 'NBA',
            slug: 'national-basketball-league',
            sport_slug: 'basketball',
            sport: 3,
            status: {
              is_live: true
            }
          }
        },
        allIds: [
          '1',
          '2',
          '3'
        ]
      }
    }
    
    let competitions = Object.values(data.competitions.byId)
    
    // _.chain(arr) keeps returning `lodash` objects
    // so I don't have to call it separately for every action
    let filteredCompetitions = _.chain(competitions)
      .groupBy(i => i.status.is_live)
      .mapValues(i => _.groupBy(i, 'sport'))
      .value() // returns the final value
      
    console.log(filteredCompetitions)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

    【讨论】:

    • 感谢您的帮助。我试过这个,我认为它可以在sport 上没有状态/is_live 参考。 let filteredCompetitions = _.chain(competitions) .groupBy('sport') .value() // returns the final value _.forEach(filteredCompetitions, function(value, key) { filteredCompetitions[key] = _.groupBy(filteredCompetitions[key], function(item) { return item.status.is_live; }); }); console.log(filteredCompetitions)也许有更优雅的方式来做到这一点?
    猜你喜欢
    • 2019-02-19
    • 2023-01-09
    • 2018-06-02
    • 2019-12-22
    • 2011-07-02
    • 2019-12-27
    • 1970-01-01
    • 2020-06-21
    • 2022-12-22
    相关资源
    最近更新 更多