按照键或值对对象数组进行排序

4
考虑这个问题:
[{name:'John'},{age:25},{address:'some street'}]

正如您所看到的,这些键都没有一个一致的名称,因此我无法使用。

arr.sort((a,b)=> a.consistentKey < b.consistentKey);

如何按名称和值进行排序?

以下内容按字母顺序排列:

[{address:'some street'},{age:25},{name:'John'}]

2
由于对象没有一致的属性名称或类型,它们是不可比较的,我想知道您如何想要对它们进行排序。 - Bergi
@JohnSnow 我认为Thomas的意思是,像这样对对象进行排序非常不寻常,你可能在错误地建模数据。你有一个包含3个对象的数组,每个对象只有一个属性,但看起来你应该有一个不带数组的对象,该对象包含所有3个属性。 - 4castle
如果数组中有第四个对象,其值为{ age: 26, address: 'another street' },您是否期望此对象在排序后的数组中位于索引0还是索引2?换句话说,对象的键首先进行排序,然后按其值对具有相同键的任何对象进行排序吗?或者您有其他想法吗?或者数组中的每个元素都是仅具有单个属性的对象? - Scott Schupbach
@4castle 我明白,数据建模不在我的控制范围内,我只需要完成任务。我同意,这是一项可怕的任务。 - JohnSnow
@ScottSchupbach 每个对象只能有一个键和一个值。 - JohnSnow
显示剩余7条评论
4个回答

1
如果你想按键值先排序,然后再按值进一步排序,可以尝试以下方法:

var a = [{name:'John'},{age:25},{address:'some street'}];
        
    alert(JSON.stringify(a.sort((a, b) => {
      nameA = Object.keys(a)[0];
      nameB = Object.keys(b)[0];
    
      if (nameA < nameB) {
        return -1;
      }
      if (nameA > nameB) {
        return 1;
      }
    
      // names must be equal
      return 0;
    })));

这里我只考虑了一个键,但您可以随时将其扩展到多个键,并且同样地,您也可以根据值进一步进行排序。


你能在控制台输出答案吗?alert 只会显示 [object object]。 - JohnSnow
即使控制台也会打印对象对象,除了在Chrome中。我已经将内容字符串化以进行调试。最重要的是,这段代码应该可以工作。 - binariedMe
1
console.dir(someObject) 可以让你在控制台中查看对象的内容。 - JacobIRR

0
如果您使用Object.keys提取键名,那么您可以获取所需的值以执行比较:
[{name: 'John'}, {age: 25}, {address:'some street'}].sort((a, b) => {
  const keyA = Object.keys(a)[0]
  const valA = a[keyA]
  const keyB = Object.keys(b)[0]
  const valB = a[keyB]

  if (keyA > keyB) {
    return 1
  } else if (keyA < keyB) {
    return -1
  } else /* equal */ {
   if (valA > valB) {
      return 1
    } else if (valA < valB) {
      return -1
    } else /* equal */ {
      return 0
    }
  }
})

0

你可以用以下方法来实现:

input.sort((a, b) => {
  const keya = Object.keys(a)[0];
  const keyb = Object.keys(b)[0];

  return keya.localeCompare(keyb) || a[keya].localeCompare(b[keyb]);
});

使用localeCompare既更短,又能更好地应对不同的语言环境。


0
以下是我会使用的解决方案。该解决方案提供了仅键排序、仅值排序、键然后值排序和值然后键排序。
class FunkySort {
  sort (sortType) {
    switch (sortType) {
      case 'keysOnly':
        return data => this._sortByKey(data);
      case 'valuesOnly':
        return data => this._sortByValue(data);
      case 'valuesPrimary':
        return data => {
          data = this._sortByKey(data);
          return this._sortByValue(data);
        };
      case 'keysPrimary':
        return data => {
          data = this._sortByValue(data);
          return this._sortByKey(data);
        };
    }
  }

  _sortByKey (data) {
    return data.sort((a, b) => {
      var keyA = Object.keys(a)[0];
      var keyB = Object.keys(b)[0];
      return keyA < keyB ? -1 : keyA > keyB ? 1 : 0;
    });
  }

  _sortByValue (data) {
    return data.sort((a, b) => {
      // note that in Node >=v7 you could use `Object.values()`, but not in <v7.0
      var valueA = a[Object.keys(a)[0]];
      var valueB = b[Object.keys(b)[0]];
      return valueA < valueB ? -1 : valueA > valueB ? 1 : 0;
    });
  }
}

const dataArr = [{name:'John'},{age:25},{address:'some street'}];
const fs = new FunkySort();
fs.sort('keysPrimary')(dataArr);

请注意,fs.sort是一个柯里化函数。第一次调用设置要执行的排序类型,因此fs.sort('keysPrimary')返回一个函数,该函数接受一个对象数组并首先按值排序,然后按键排序,从而得到按键排序的对象数组,如果有多个具有相同键的对象,则按值排序。
如果您不需要这种类型排序的灵活性,那么只需使用_sortByKey辅助方法即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接