将javascript数组中的重复值分组在一起,然后按值名称升序对这些组进行排序

Posted

技术标签:

【中文标题】将javascript数组中的重复值分组在一起,然后按值名称升序对这些组进行排序【英文标题】:Group duplicates values in javascript array together, then sort those groups by their value name ascending 【发布时间】:2019-01-08 04:40:45 【问题描述】:

我有一个对象数组,我必须循环并按属性名称“tagColor”对重复值进行分组,然后我需要按名称对分组对象进行排序。我实现了按颜色排序的第一步,现在我只需要按名称对这些组进行排序,在 Angular 4 中实现这一点,打字稿

这里是数组列表

 tags =    [
      
        "tagType": 
          "name": "a",
          "tagColor": "#0000FF"
        
      ,
      

        "tagType": 
          "name": "a",
          "tagColor": "#FF0000"
        
      ,
      

        "tagType": 
          "name": "c",
          "tagColor": "#FF0000",
        
      ,
      
        "tagType": 
          "name": "b",
          "tagColor": "#FF0000",
        
      ,
      
        "tagType": 
          "name": "b",
          "tagColor": "#0000FF",
        
      
    ]

我的按 tagColor 排序的函数:

tags.sort((a, b) => a.tagType.tagColor.localeCompare(b.tagType.tagColor));

这仅按颜色分组,但如何按字母顺序对这些组进行排序?

【问题讨论】:

您只需要一个排序。颜色是主键,所以先比较一下。如果两个元素的颜色相同,那么比较结果应该是比较次键的结果。 【参考方案1】:

您可以使用单个排序调用,如果比较标签的结果为 0,则按名称进行比较:

tags.sort((a, b) => 
    let result = b.tagType.tagColor.localeCompare(a.tagType.tagColor);
    if(result == 0) 
        return a.tagType.name.localeCompare(b.tagType.name);
    
    return result;
);

或者更简洁但可读性较差的版本:

tags.sort((a, b) =>
    b.tagType.tagColor.localeCompare(a.tagType.tagColor) // if this is 0 (aka falsy) return the other value
        || a.tagType.name.localeCompare(b.tagType.name));

【讨论】:

感谢它的确切工作,你如何实践那些我开发时间不长的东西?谢谢回答,去学习这个 @AlexFF1 不知道我明白了,你的意思是我是怎么知道怎么做的.. 不知道.. 过了一会儿它主要是找你:) 谢谢我明白了,越练越自然,谢谢【参考方案2】:

除了按颜色给定的顺序外,您还可以使用定义的自定义颜色顺序以及反映顺序的对象。

对于在对象中找不到的颜色,您可以采用默认值将此颜色移动到定义的位置,到开始处,

(order[a.tagType.tagColor] || -Infinity) - (order[b.tagType.tagColor] || -Infinity)

到最后,

(order[a.tagType.tagColor] || Infinity) - (order[b.tagType.tagColor] || Infinity)

或介于两者之间。

(colorOrder[a.tagType.tagColor] || 1.5) - (colorOrder[b.tagType.tagColor] || 1.5)

var tags = [ tagType:  name: "a", tagColor: "#0000FF"  ,  tagType:  name: "a", tagColor: "#FF0000"  ,  tagType:  name: "c", tagColor: "#FF0000"  ,  tagType:  name: "b", tagColor: "#FF0000"  ,  tagType:  name: "b", tagColor: "#0000FF"  ],
	colorOrder =  "#0000FF": 1, "#FF0000": 2 ;


tags.sort((a, b) =>
    colorOrder[a.tagType.tagColor] - colorOrder[b.tagType.tagColor] ||
    a.tagType.name.localeCompare(b.tagType.name)
);

console.log(tags);
.as-console-wrapper  max-height: 100% !important; top: 0; 

【讨论】:

【参考方案3】:

在排序功能中先按颜色比较,然后按名称比较。比较函数返回 -1, 0, 1。如果 b 应该在 a 之后,则函数返回 -1 - 不需要排序,如果 b 等于 a,函数返回 0 - 不需要排序,如果b 需要在 a 之前,然后函数返回 1 - 需要排序。由于 -1 和 0 评估为 false 并且 1 评估为 true 基本上排序函数返回 true 需要排序或 false 不需要排序。因此,如果您按颜色进行比较并且需要排序,则传递 colorSort 值,如果不需要对颜色进行排序,则传递 nameSort 值

tags.sort((a, b) => 
  let colorSort = a.tagType.tagColor.localeCompare(b.tagType.tagColor);
  let nameSort = a.tagType.name.localeCompare(b.tagType.name);
  return (colorSort)? colorSort:nameSort;
);

【讨论】:

以上是关于将javascript数组中的重复值分组在一起,然后按值名称升序对这些组进行排序的主要内容,如果未能解决你的问题,请参考以下文章

按数组中的多个属性对对象进行分组,然后将它们的值相加

将两个javascript数组加在一起[重复]

根据JavaScript中的属性值从对象数组中选择[重复]

在 LINQ 中按特定列分组 [重复]

如何使用JavaScript将循环内数组中的所有项目相乘[重复]

JavaScript:查找值是不是在数组中的对象内的最佳方法[重复]