【问题标题】:Javascript sort array by "groups" and maintain orderJavascript按“组”排序数组并维护顺序
【发布时间】:2020-03-31 13:09:18
【问题描述】:

我有一个如下所示的数据集:

[
{
    "name": "Item1",
    "section": "section1",
    "total": 3,
}, {
    "name": "Item1",
    "section": "section2",
    "total": 4,
}{
    "name": "Item1",
    "section": "section3",
    "total": 7,
}, {
    "name": "Item2",
    "section": "section1",
    "total": 1,
}, {
    "name": "Item2",
    "section": "section2",
    "total": 2,
}, {
    "name": "Item2",
    "section": "section3",
    "total": 3,
    }
]

我只需要按第 3 节项目中的总值对数组进行排序,但要保持每个名称的顺序(第 1 节、第 2 节、第 3 节)。所以对于这个例子,Item2 应该将它的所有 3 行移到 Item1 之上。我试过按多个项目排序,但这并不能保持我需要的排序。我应该只取最小/最大的,抓取相关项目并将它们放入一个新数组并重复,还是有更合乎逻辑的方法来完成这个?

如果有什么我可以利用的东西,我也会使用 angular 和 primeng 网格。

【问题讨论】:

  • 你需要一个稳定的排序,内置的 IIRC 不稳定。
  • 你说的我试过按多个项目排序,是什么意思?这对我来说听起来不对。
  • 您是否总是在一个组中包含三个项目?请添加想要的结果。

标签: javascript arrays angular sorting


【解决方案1】:

我将使用name 作为键和total 作为section 等于section3 的项目的值创建一个映射。然后您可以使用地图进行排序。

这将按照section3total 的值对所有项目进行排序,并保留排序值匹配的原始排序顺序。

const map = new Map<string, number>(this.data
  .filter(x => x.section === 'section3')
  .map(x => [ x.name, x.total ]));

this.sorted = this.data.slice()
  .sort((a, b) => map.get(a.name) - map.get(b.name));

这确实依赖于您在问题中指定的结构化和排序数据。

演示:https://stackblitz.com/edit/angular-fsswdq

【讨论】:

    【解决方案2】:

    你可以

    • 收集同一组的所有对象并得到总数进行排序,
    • 按组total值排序,
    • 获取所有对象的平面数组。

    const
        data = [{ name: "Item1", section: "section1", total: 3 }, { name: "Item1", section: "section2", total: 4 }, { name: "Item1", section: "section3", total: 7 }, { name: "Item2", section: "section1", total: 1 }, { name: "Item2", section: "section2", total: 2 }, { name: "Item2", section: "section3", total: 3 }],
        result = Object
            .values(data.reduce((r, o) => {
                r[o.name] = r[o.name] || { payload: [] };
                r[o.name].payload.push(o);
                if (o.section === 'section3') r[o.name].total = o.total;
                return r;
            }, {}))
            .sort(({ total: a }, { total: b }) => a - b)
            .flatMap(({ payload }) => payload);
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      【解决方案3】:

      var array = [
      {
          "name": "Item1",
          "section": "section1",
          "total": 3,
      }, {
          "name": "Item1",
          "section": "section2",
          "total": 4,
      },{
          "name": "Item1",
          "section": "section3",
          "total": 7,
      }, {
          "name": "Item2",
          "section": "section1",
          "total": 1,
      }, {
          "name": "Item2",
          "section": "section2",
          "total": 2,
      }, {
          "name": "Item2",
          "section": "section3",
          "total": 3,
          }
      ];
      
      array = array.sort((o1, o2)=>{
      
      if(o1.section === o2.section && o1.section === 'section3') {
         return o1.total - o2.total;
      } else {
        return o1.section === 'section3' ? 1 : -1;
      }
      });
      
      console.log(array);

      这是输出

      [
        {
          "name": "Item1",
          "section": "section1",
          "total": 3
        },
        {
          "name": "Item1",
          "section": "section2",
          "total": 4
        },
        {
          "name": "Item2",
          "section": "section1",
          "total": 1
        },
        {
          "name": "Item2",
          "section": "section2",
          "total": 2
        },
        {
          "name": "Item2",
          "section": "section3",
          "total": 3
        },
        {
          "name": "Item1",
          "section": "section3",
          "total": 7
        }
      ]
      

      【讨论】:

        【解决方案4】:

        您首先需要将name 的数据集“分组”,然后按total 进行排序。

        let items = [{
          "name": "Item1",
          "section": "section1",
          "total": 3,
        }, {
          "name": "Item1",
          "section": "section2",
          "total": 4,
        }, {
          "name": "Item1",
          "section": "section3",
          "total": 7,
        }, {
          "name": "Item2",
          "section": "section1",
          "total": 1,
        }, {
          "name": "Item2",
          "section": "section2",
          "total": 2,
        }, {
          "name": "Item2",
          "section": "section3",
          "total": 3,
        }];
        
        let groups = {};
        
        for (let item of items) {
          if (!groups[item.name]) {
            groups[item.name] = {
              data: []
            };
          }
        
          // Grouping by `name`
          groups[item.name].data.push(item);
        
          // Store the `total`
          if (item.section == "section3") {
            groups[item.name].key = item.total;
          }
        }
        
        // sort the groups, this will maintain the order of sections (1,2 and 3) in each group
        let sortedGroups = Object.values(groups).sort((a, b) => {
          return a.key - b.key; // ascending
        });
        
        // then flatten the groups
        let flatten = [].concat(...sortedGroups.map(x => x.data));
        
        console.log(flatten);

        【讨论】:

          【解决方案5】:

          优先排序

          const data = [{"name":"Item1","section":"section1","total":3},{"name":"Item1","section":"section2","total":4},{"name":"Item1","section":"section3","total":7},{"name":"Item2","section":"section1","total":1},{"name":"Item2","section":"section2","total":2},{"name":"Item2","section":"section3","total":3}];
          console.log(
            data.sort((a, b) => {
              const diff = a.total - b.total;
              if (diff) return diff;
              return b.section.localeCompare(a.section);
            })
          );
          .as-console-row {color: blue!important}

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-03-03
            • 1970-01-01
            • 2019-08-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多