es6 맵 객체의 항목을 정렬 할 수 있습니까?
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 맵 객체의 항목을 정렬 할 수 있습니까?
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()하여 배열은 각 요소의 문자열 변환에 따라 각 문자의 유니 코드 코드 포인트 값에 따라 정렬됩니다. 따라서 2-1, 0-1, 3-1올바르게 정렬됩니다.
var mapAsc = new Map([...map.entries()].sort((a,b) => a[0] > b[0]));화살표 함수 (, λ)을 사용하여
2-1,foo에 0-1,bar와3-1,baz
(a,b) => a[0] > b[0]!
...점은 중요한 그렇지 않으면 당신은 MapIterator 정렬하려고하는
1e-9에 넣는 것과 같은 숫자로 잘못된 결과가 표시 100됩니다. 숫자로 작동하는 코드 :new Map([...map.entries()].sort((e1, e2) => e1[0] - e2[0]))
new Map([...map].sort((a, b) =>
// Some sort function comparing keys with a[0] b[0] or values with a[1] b[1]
// Be sure to return -1 if lower and, if comparing values, return 0 if equal
))
예를 들어, 같을 수있는 값 문자열을 비교하면 [1]에 액세스하고 0을 반환하는 같음 조건이있는 정렬 함수를 전달합니다.
new Map([...map].sort((a, b) => (a[1] > b[1] && 1) || (a[1] === b[1] ? 0 : -1)))
같을 수없는 (동일한 문자열 키가 서로 덮어 쓰기) 키 문자열을 비교하면 equals 조건을 건너 뛸 수 있습니다. 그러나 다음과 같은 경우 lazy를 a[0] > b[0]잘못 반환 하면 false (0으로 처리됨, 즉 같음)가 반환되므로 명시 적으로 -1을 반환해야합니다 a[0] < b[0].
new Map([...map].sort((a, b) => a[0] > b[0] ? 1 : -1))
.entries()에서 [...map.entries()](많은 답변에서 제안) 아마 멀리 당신을위한 JS 엔진 최적화합니다 않는지도의 추가 반복을 추가, 중복입니다.
간단한 테스트 케이스에서 질문이 요구하는 것을 다음과 같이 할 수 있습니다.
new Map([...map].sort())
...되는 키 모든 문자열 경우 으깨 콤마 가입 키 값 등 문자열 강제를 비교 '2-1,foo'하고 '0-1,[object Object]'새로운 신청서와 새로운 맵을 반환 :
참고 : {}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]같이, 정렬 기능에. 우리가 반환해야 함을 참고 -1하고 1있지, 이전과 이후 false또는 0원시와 같은 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']
])
// For keys, we don't need an equals case, because identical keys overwrite
const sortStringKeys = (a, b) => a[0] > b[0] ? 1 : -1
// For values, we do need an equals case
const sortStringValues = (a, b) => (a[1] > b[1] && 1) || (a[1] === b[1] ? 0 : -1)
console.log('By keys:', new Map([...map].sort(sortStringKeys)))
console.log('By values:', new Map([...map].sort(sortStringValues)))
변환 Map사용하여 배열 Array.from, 정렬 배열로 변환 다시 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()않았다
아이디어는지도의 키를 배열로 추출하는 것입니다. 이 배열을 정렬하십시오. 그런 다음이 정렬 된 배열을 반복하고 정렬되지 않은 맵에서 값 쌍을 가져 와서 새 맵에 넣습니다. 새지도는 정렬 된 순서로 표시됩니다. 아래 코드는 구현입니다.
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....
불행히도 ES6에서는 실제로 구현되지 않았습니다. ImmutableJS의 OrderedMap.sort () 또는 Lodash의 _.sortBy () 에이 기능이 있습니다 .
한 가지 방법은 항목 배열을 가져 와서 정렬 한 다음 정렬 된 배열로 새 맵을 만드는 것입니다.
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);
})
아래 스 니펫은 키별로 지정된지도를 정렬하고 키를 키-값 개체에 다시 매핑합니다. 내 맵이 string-> string 객체 맵이기 때문에 localeCompare 함수를 사용했습니다.
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;
});
결과: [{t:'tt'}, {x:'xx'}, {y: 'yy'}];
내가보기에 현재지도를 제대로 정렬하는 것은 불가능합니다.
맵이 배열로 변환되고 이런 방식으로 정렬되는 다른 솔루션에는 다음과 같은 버그가 있습니다.
var a = new Map([[1, 2], [3,4]])
console.log(a); // a = Map(2) {1 => 2, 3 => 4}
var b = a;
console.log(b); // b = Map(2) {1 => 2, 3 => 4}
a = new Map(); // this is when the sorting happens
console.log(a, b); // a = Map(0) {} b = Map(2) {1 => 2, 3 => 4}
정렬은 새 개체를 만들고 정렬되지 않은 개체에 대한 다른 모든 포인터가 손상됩니다.
세부 사항을 파악하는 데 2 시간이 소요되었습니다.
질문에 대한 답변은 이미 https://stackoverflow.com/a/31159284/984471 에서 제공됩니다.
그러나 질문에는 일반적인 것이 아닌 키가 있습니다. 설명이
있는 명확하고 일반적인 예는 다음 과 같이 좀 더 명확성을 제공합니다.
.
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 객체를 정렬하지 않고 Map을 수행하기 전에 먼저 정렬을 준비하는보다 현실적인 예일 것입니다. 이렇게하면 구문이 실제로 매우 압축됩니다. 이와 같이 map 함수 앞에 정렬을 적용 할 수 있습니다. map 앞에 sort 함수를 사용하면됩니다 (JSX 구문을 사용하여 작업중인 React 앱의 예).
내가 API에서 가져온 배열의 Javascript 객체 속성에 따라 정렬 된 값이 더 작 으면 -1을 반환하고 그렇지 않으면 0을 반환하는 화살표 함수를 사용하여 내부 정렬 함수를 정의합니다.
report.ProcedureCodes.sort((a, b) => a.NumericalOrder < b.NumericalOrder ? -1 : 0).map((item, i) =>
<TableRow key={i}>
<TableCell>{item.Code}</TableCell>
<TableCell>{item.Text}</TableCell>
{/* <TableCell>{item.NumericalOrder}</TableCell> */}
</TableRow>
)
let map = new Map();
map.set('2-1', "foo");
map.set('0-1', "bar");
map.set('3-1', "baz");
let mapAsc = new Map([...map.entries()].sort());
console.log(mapAsc);
// Map(3) {"0-1" => "bar", "2-1" => "foo", "3-1" => "baz"}