如何先按一个属性对数组排序,然后再按属性字母顺序对另一个数组排序?

时间:2019-02-07 17:05:28

标签: javascript json sorting

var sortedFeatures = features.sort(function(a,b){
    if(a.properties.Project_Year < b.properties.Project_Year) {return 1}
    if(a.properties.Project_Year > b.properties.Project_Year) {return -1 }
    return 0;
}) 

目前,此代码的作用是按年份对我的属性进行排序,这是第一部分。

第二部分现在有一个名为Project_Name的属性。我想按年份对文件进行排序,但是在这种排序中,我还想按字母顺序添加排序。

我的输出已经建立。我想知道如何调整此代码以获得我正在寻找的正确排序。

3 个答案:

答案 0 :(得分:0)

执行此操作的一种好方法是查看排序中的return 0;部分-当Project_Year属性都相同时会发生这种情况。如果用Project_Name属性上的字母比较代替它,则应得到所需的答案:

var sortedFeatures = features.sort(function(a,b){
   if(a.properties.Project_Year < b.properties.Project_Year) {return 1}
   if(a.properties.Project_Year > b.properties.Project_Year) {return -1 }

   //compare names alphabetically
   return a.properties.Project_Name.localeCompare(b.properties.Project_Name);
});

请注意,这不能处理Project_Name不是有效字符串(例如undefinednull)的情况,在这种情况下程序将引发错误,因此如果这是一种有效的可能性,则在其中抛出一些if()语句以防止这种情况发生,例如

var sortedFeatures = features.sort(function(a,b){
   if(a.properties.Project_Year < b.properties.Project_Year) {return 1}
   if(a.properties.Project_Year > b.properties.Project_Year) {return -1 }

   //compare names alphabetically
   const projectNameA = a.properties.Project_Name || ""; //default to empty string
   const projectNameB = b.properties.Project_Name || ""; 
   return projectNameA.localeCompare(projectNameB);
});

答案 1 :(得分:0)

compareFunction首先按features的降序对Project_Year进行排序。如果年份相同,则差异为零。这个falsy值会强制其检查第二个条件,并根据Project_Name

进行比较

var features = [
  { properties : { Project_Name : 'B', Project_Year : 2018 } },
  { properties : { Project_Name : 'A', Project_Year : 2018 } },
  { properties : { Project_Name : 'C', Project_Year : 2018 } },
  { properties : { Project_Name : 'A', Project_Year : 2019 } },
  { properties : { Project_Name : 'B', Project_Year : 2019 } },
];

var sortedFeatures = features.sort(function(a, b) {
  return b.properties.Project_Year - a.properties.Project_Year 
          || a.properties.Project_Name.localeCompare(b.properties.Project_Name)
})

console.log(sortedFeatures)

此数字按年份降序排序,然后在一年之内根据字母顺序排序。

答案 2 :(得分:0)

这是一个相当简单的任务。只需比较年份,如果它们相同,则可以比较名称。

var features = [
  { Project_Name : 'C', properties : { Project_Year : new Date(2019, 1, 0) } },
  { Project_Name : 'A', properties : { Project_Year : new Date(2019, 1, 0) } },
  { Project_Name : 'B', properties : { Project_Year : new Date(2019, 1, 0) } },
  { Project_Name : 'C', properties : { Project_Year : new Date(2018, 1, 0) } },
  { Project_Name : 'A', properties : { Project_Year : new Date(2017, 1, 0) } },
  { Project_Name : 'B', properties : { Project_Year : new Date(2018, 1, 0) } }
];

/** Sort by year, followed by name */
var sortedFeatures = features.sort(function(a, b) {
  var yearDiff = a.properties.Project_Year - b.properties.Project_Year;
  if (yearDiff === 0) {
    return a.Project_Name.localeCompare(b.Project_Name);
  }
  return yearDiff;
});

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


动态方法

如果您想要更通用的实现,可以签出this example。我创建了此示例的扩展实现,该实现查询嵌套属性的范围。

var sort_by;
(function() {
  var default_cmp = (a, b) => a == b ? 0 : (a < b ? -1 : 1);
  getCmpFunc = (primer, reverse) => {
    let dfc = default_cmp, cmp = default_cmp;
    if (primer) {
      cmp = (a, b) => dfc(primer(a), primer(b));
    }
    if (reverse) {
      return (a, b) => -1 * cmp(a, b);
    }
    return cmp;
  };
  queryValue = function(v, scope) {
    return scope == null || scope.length === 0 ? v : queryValue(v[scope.shift()], scope);
  };
  sort_by = function() {
    let fields = [], n_fields = arguments.length, field, name, reverse, cmp;
    for (var i = 0; i < n_fields; i++) {
      field = arguments[i];
      if (typeof field === 'string') {
        name = field;
        cmp = default_cmp;
      } else {
        name = field.name;
        cmp = getCmpFunc(field.primer, field.reverse);
      }
      fields.push({ name: name, cmp: cmp });
    }
    return (A, B) => {
      let a, b, result;
      for (var i = 0; i < n_fields; i++) {
        result = 0;
        a = queryValue(A, fields[i].name.split('.'));
        b = queryValue(B, fields[i].name.split('.'));
        result = fields[i].cmp(a, b);
        if (result !== 0) break;
      }
      return result;
    };
  };
}());

var features = [
  { Project_Name : 'C', properties : { Project_Year : new Date(2019, 1, 0) } },
  { Project_Name : 'A', properties : { Project_Year : new Date(2019, 1, 0) } },
  { Project_Name : 'B', properties : { Project_Year : new Date(2019, 1, 0) } },
  { Project_Name : 'C', properties : { Project_Year : new Date(2018, 1, 0) } },
  { Project_Name : 'A', properties : { Project_Year : new Date(2017, 1, 0) } },
  { Project_Name : 'B', properties : { Project_Year : new Date(2018, 1, 0) } }
];

/** Sort by year (decending), followed by name (ascending) */
var sortedFeatures = features.sort(sort_by(
  { name: 'properties.Project_Year', reverse: true, primer : (d) => d.getTime() },
  'Project_Name' // scalar string value
));

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