【问题标题】:Group an array of object having nested level对具有嵌套级别的对象数组进行分组
【发布时间】:2021-01-19 11:56:13
【问题描述】:

我有一个表格模式数组对象,如下所示,最多 n 级。可以是任何父子的记录

var records = [
  { country: "USA", state: "FLORIDA", city: "city1" },
  { country: "USA", state: "FLORIDA", city: "city2" },
  { country: "USA", state: "FLORIDA", city:"city3" },
  { country: "USA", state: "ALASKA" },
  { country: "USA", state: "ALBAMA" },
]

var columns = ["country","state","city"]  // upto n column

我需要按以下格式对第 n 级进行分组,因为可以有 n 级关系,按以下格式分组记录

{
  sequencer: 1, value: 'USA', loop: [
    { sequencer: 1, value: 'FLORIDA', loop: [
      { sequencer: 1, value: 'city1' },
      { sequencer: 2, value: 'city2' },
      { sequencer: 3, value: 'city3' },
    ], },
    { sequencer: 2, value: 'ALASKA' },
    { sequencer: 3, value: 'ALBAMA' },
  ],
}

有人可以编写一个递归函数来对 n 级列对象进行分组吗? 谢谢

【问题讨论】:

    标签: javascript arrays typescript ecmascript-6


    【解决方案1】:

    您可以通过避免不需要的循环属性来对数据进行分组。

    const
        data = [{ country: "USA", state: "FLORIDA", city: "city1" }, { country: "USA", state: "FLORIDA", city: "city2" }, { country: "USA", state: "FLORIDA", city: "city3" }, { country: "USA", state: "ALASKA" }, { country: "USA", state: "ALBAMA" }],
        keys = ['country', 'state', 'city'],
        result = data.reduce((loop, o) => {
            keys
                .map(k => o[k])
                .filter(Boolean)
                .reduce((r, value) => {
                    let temp = (r.loop ??= []).find(q => q.value === value);
                    if (!temp) r.loop.push(temp = { sequence: r.loop.length + 1, value });
                    return temp;
                }, { loop });
            return loop;
        }, []);
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 感谢您的回答。你能告诉我如何将输出列键更新为值(静态键),如下所示 { sequencer: 1, value: 'USA', loop: [ {sequencer: 1, value: 'FLORIDA', loop: [ {定序器:1,值:'city1'},{定序器:2,值:'city2'},{定序器:3,值:'city3'},],},{定序器:2,值:'ALASKA'} , {sequencer: 3, value: 'ALBAMA'}, ], }
    • 这使代码更容易,因为您不再需要动态键来查找和新对象。请参阅编辑。
    【解决方案2】:

    我最近回复了similar question。您可以使用flatMap 和递归来编写您的transform -

    const transform = ([ name, ...more ], { value, loop = [{}] }, r = {}) =>
      name === undefined
        ? [ r ]
        : loop.flatMap(t => transform(more, t, { [name]: value, ...r }))
    
    const records =
      {sequencer:1,value:'USA',loop:[{sequencer:1,value:'FLORIDA',loop:[{sequencer:1,value:'city1'},{sequencer:2,value:'city2'},{sequencer:3,value:'city3'}]},{sequencer:2,value:'ALASKA'},{sequencer:3,value:'ALBAMA'}]}
    
    const columns =
      ['country', 'state', 'city']
    
    const result =
      transform(["country", "state", "city"], records)
      
    console.log(JSON.stringify(result, null, 2))

    function 语句等效于上面的 => 表达式 -

    function transform
      ( [ name, ...more ]
      , { value, loop = [{}] }
      , r = {}
      )
      { if (name === undefined)
          return [ r ]
        else 
          return loop.flatMap
            ( t =>
                transform
                  ( more
                  , t
                  , { [name]: value, ...r }
                  )
            )
      }
    

    阅读original Q&A 了解有关此技术的更多信息。

    【讨论】:

    • 谢谢,我可以看到它,在这里我正在寻找反之亦然。我需要将记录分组到 n 级。您可以为相同的情况编写反之亦然的功能吗?谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 2021-10-19
    相关资源
    最近更新 更多