是否可以对es6 Map对象的条目进行排序?
var map = new Map();
map.set('2-1', foo);
map.set('0-1', bar);
导致结果如下:
map.entries = {
0: {"2-1", foo },
1: {"0-1", bar }
}
是否可以根据键对条目进行排序?
map.entries = {
0: {"0-1", bar },
1: {"2-1", foo }
}
是否可以对es6 Map对象的条目进行排序?
var map = new Map();
map.set('2-1', foo);
map.set('0-1', bar);
导致结果如下:
map.entries = {
0: {"2-1", foo },
1: {"0-1", bar }
}
是否可以根据键对条目进行排序?
map.entries = {
0: {"0-1", bar },
1: {"2-1", foo }
}
根据 MDN 文档:
Map 对象迭代它的元素是按插入顺序进行的。
你可以这样做:
var map = new Map();
map.set('2-1', "foo");
map.set('0-1', "bar");
map.set('3-1', "baz");
var mapAsc = new Map([...map.entries()].sort());
console.log(mapAsc)
使用 .sort()
方法时,请记住数组是根据每个字符的 Unicode 代码点值进行排序的,根据每个元素的字符串转换进行排序。所以2-1, 0-1, 3-1
将被正确地排序。
var mapAsc = new Map([...map.entries()].sort((a,b) => a[0] > b[0]));
,使用箭头函数(lambda)。 - Jimmy Chandra2-1,foo
与0-1,bar
和3-1,baz
进行词法比较。 - Bergi(a,b) => a[0] > b[0]
! - Bergi...
点,你就在尝试对一个MapIterator进行排序,这些...
点非常重要。 - muttonUp1e-9
之类的数字放在100
之后,会得到无效结果。 适用于数字的代码:new Map([...map.entries()].sort((e1, e2) => e1[0] - e2[0]))
- cdalxndr new Map([...map].sort((a, b) =>
// Some sort function comparing keys with a[0] b[0] or values with a[1] b[1]
))
如果你期望的是字符串:正常情况下,对于.sort
您需要返回-1(较低)和0(相等);对于字符串,推荐的方法是使用.localeCompare()
,它可以正确地处理特殊字符,例如位置因用户区域设置而异的ä
。
因此,这里有一种通过键名排序映射的简单方法:
new Map([...map].sort((a, b) => String(a[0]).localeCompare(b[0])))
...并通过字符串值:
new Map([...map].sort((a, b) => String(a[1]).localeCompare(b[1])))
这些代码是类型安全的,如果遇到非字符串键或值,它们不会抛出错误。代码中的 String()
强制将 a
转换为字符串(并且有助于可读性),.localeCompare()
自身强制其参数成为一个字符串而不会产生错误。
简而言之:使用 ...map
即可,无需使用 ...map.entries()
;未传递排序函数的懒惰 .sort()
可能存在由于字符串转换引起奇怪的边缘情况错误。
[...map.entries()]
中的 .entries()
(在许多答案中建议使用)是冗余的,除非 JS 引擎为您优化掉了该迭代的额外开销。
在简单测试用例中,您可以使用以下代码来实现所需功能:
new Map([...map].sort())
如果键全部为字符串,则比较压缩和强制转换逗号连接的键值字符串,例如'2-1,foo'
和'0-1,[object Object]'
,返回一个新的具有新插入顺序的Map:
注意:如果在SO的控制台输出中仅看到{}
,请查看您真实的浏览器控制台
const map = new Map([
['2-1', 'foo'],
['0-1', { bar: 'bar' }],
['3-5', () => 'fuz'],
['3-2', [ 'baz' ]]
])
console.log(new Map([...map].sort()))
然而,依赖强制类型转换和字符串化并不是一个好的实践方式。你可能会得到一些意料之外的结果:
const map = new Map([
['2', '3,buh?'],
['2,1', 'foo'],
['0,1', { bar: 'bar' }],
['3,5', () => 'fuz'],
['3,2', [ 'baz' ]],
])
// Compares '2,3,buh?' with '2,1,foo'
// Therefore sorts ['2', '3,buh?'] ******AFTER****** ['2,1', 'foo']
console.log('Buh?', new Map([...map].sort()))
// Let's see exactly what each iteration is using as its comparator
for (const iteration of map) {
console.log(iteration.toString())
}
像这样的错误很难调试 - 不要冒险!
如果您想按键或值排序,最好在排序函数中明确访问它们,如上所示使用a[0]
和b[0]
;或者在函数参数中使用数组解构:
const map = new Map([
['2,1', 'this is overwritten'],
['2,1', '0,1'],
['0,1', '2,1'],
['2,2', '3,5'],
['3,5', '2,1'],
['2', ',9,9']
])
// Examples using array destructuring. We're saying 'keys' and 'values'
// in the function names so it's clear and readable what the intent is.
const sortStringKeys = ([a], [b]) => String(a).localeCompare(b)
const sortStringValues = ([,a], [,b]) => String(a).localeCompare(b)
console.log('By keys:', new Map([...map].sort(sortStringKeys)))
console.log('By values:', new Map([...map].sort(sortStringValues)))
如果你需要一种不同的比较方式而不是字符串按字母顺序排列,一定要记得始终返回-1
和1
表示前面和后面,而不是false
或0
,就像使用原始的a[0] > b[0]
那样,因为它被视为相等。
使用Array.from
将Map
转换为数组,对数组进行排序,然后将其转换回Map
,例如:
new Map(
Array
.from(eventsByDate)
.sort((a, b) => {
// a[0], b[0] is the key of the map
return a[0] - b[0];
})
)
[...map.values()].sort()
对我来说不起作用,但是 Array.from(map.values()).sort()
却可以。 - Rob Juurlink:
map[Symbol.iterator] = function* () {
yield* [...map.entries()].sort((a, b) => a[0].localeCompare(b[0]));
}
使用迭代器的优点在于只需要声明一次。在添加/删除映射条目后,对映射的新循环将使用迭代器自动反映这些变化。与大多数上面的答案所示的排序副本不同,它们仅反映映射在某个时间点的状态。
以下是使用您的初始情况的完整工作示例。
var map = new Map();
map.set('2-1', { name: 'foo' });
map.set('0-1', { name: 'bar' });
for (let [key, val] of map) {
console.log(key + ' - ' + val.name);
}
// 2-1 - foo
// 1-0 - bar
map[Symbol.iterator] = function* () {
yield* [...map.entries()].sort((a, b) => a[0].localeCompare(b[0]));
}
for (let [key, val] of map) {
console.log(key + ' - ' + val.name);
}
// 1-0 - bar
// 2-1 - foo
map.set('2-0', { name: 'zzz' });
for (let [key, val] of map) {
console.log(key + ' - ' + val.name);
}
// 1-0 - bar
// 2-0 - zzz
// 2-1 - foo
敬礼。
[...map]
和 for (… of map)
。它不会对 map.keys()
、map.entries()
或 map.values()
的迭代进行排序。例如,有人可能期望 [...map.values()]
与 [...map].map(([,value]) => value)
具有相同的输出,但应用此方法后,前者将具有插入顺序,而后者将应用此排序。 - user56reinstatemonica8[...map].sort(/* etc */);
这个想法是将您的映射键提取到一个数组中。对这个数组进行排序。然后迭代这个排序后的数组,从未排序的映射中获取其值对,并将它们放入一个新的映射中。这个新映射将被排序。以下是它的实现代码:
var unsortedMap = new Map();
unsortedMap.set('2-1', 'foo');
unsortedMap.set('0-1', 'bar');
// Initialize your keys array
var keys = [];
// Initialize your sorted maps object
var sortedMap = new Map();
// Put keys in Array
unsortedMap.forEach(function callback(value, key, map) {
keys.push(key);
});
// Sort keys array and go through them to put in and put them in sorted map
keys.sort().map(function(key) {
sortedMap.set(key, unsortedMap.get(key));
});
// View your sorted map
console.log(sortedMap);
unsortedMap.keys()
来确定。而且 keys.sort().map...
应该改为 keys.sort().forEach...
。 - faintsignal花了2个小时深入细节。
注意,问题的答案已经在https://dev59.com/vF0Z5IYBdhLWcg3wtSE8#31159284上给出。
然而,这个问题的关键不是通常的关键字,
下面提供了一个清晰且通俗易懂的带解释的例子,以提供更多的清晰度:
.
let m1 = new Map();
m1.set(6,1); // key 6 is number and type is preserved (can be strings too)
m1.set(10,1);
m1.set(100,1);
m1.set(1,1);
console.log(m1);
// "string" sorted (even if keys are numbers) - default behaviour
let m2 = new Map( [...m1].sort() );
// ...is destructuring into individual elements
// then [] will catch elements in an array
// then sort() sorts the array
// since Map can take array as parameter to its constructor, a new Map is created
console.log('m2', m2);
// number sorted
let m3 = new Map([...m1].sort((a, b) => {
if (a[0] > b[0]) return 1;
if (a[0] == b[0]) return 0;
if (a[0] < b[0]) return -1;
}));
console.log('m3', m3);
// Output
// Map { 6 => 1, 10 => 1, 100 => 1, 1 => 1 }
// m2 Map { 1 => 1, 10 => 1, 100 => 1, 6 => 1 }
// Note: 1,10,100,6 sorted as strings, default.
// Note: if the keys were string the sort behavior will be same as this
// m3 Map { 1 => 1, 6 => 1, 10 => 1, 100 => 1 }
// Note: 1,6,10,100 sorted as number, looks correct for number keys
一种方法是获取条目数组,对其进行排序,然后使用排序后的数组创建新的Map:
let ar = [...myMap.entries()];
sortedArray = ar.sort();
sortedMap = new Map(sortedArray);
但是如果你不想创建一个新的对象,而是想在同一个对象上工作,你可以这样做:
// Get an array of the keys and sort them
let keys = [...myMap.keys()];
sortedKeys = keys.sort();
sortedKeys.forEach((key)=>{
// Delete the element and set it again at the end
const value = this.get(key);
this.delete(key);
this.set(key,value);
})
var hash = {'x': 'xx', 't': 'tt', 'y': 'yy'};
Object.keys(hash).sort((a, b) => a.localeCompare(b)).map(function (i) {
var o = {};
o[i] = hash[i];
return o;
});
result: [{t:'tt'}, {x:'xx'}, {y: 'yy'}];
map = new Map([...map].sort())
ORmap = new Map([...map].sort((a,b)=>a-b))
- Manohar Reddy Poreddy