ES6 맵 객체를 정렬할 수 있습니까?
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 문서에 따르면:
맵 개체는 요소를 삽입 순서대로 반복합니다.
이런 식으로 할 수 있습니다.
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
올바르게 정렬됩니다.
단답형
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을 반환해야 합니다. 문자열의 경우 이를 올바르게 처리하고 다음과 같은 어색한 문자를 자동으로 처리하는 방법이 권장됩니다.ä
여기서 위치는 사용자 로케일에 따라 달라집니다.
문자열 키로 맵을 정렬하는 간단한 방법은 다음과 같습니다.
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()
그 자체가 오류를 범하지 않고 문자열이 되도록 주장을 강요합니다.
예를 들어 상세히 설명합니다.
tldr:...map.entries()
중복되는 것입니다, 그냥....map
괜찮아요; 그리고 게으른..sort()
정렬 함수를 전달하지 않으면 문자열 강제에 의한 이상한 에지 케이스 버그가 발생할 위험이 있습니다.
.entries()
인에[...map.entries()]
(많은 답변에서 제시) JS 엔진이 이 방법을 최적화하지 않는 한 지도의 추가 반복을 추가할 수 있습니다.
간단한 테스트 케이스에서는 다음을 사용하여 질문이 요구하는 작업을 수행할 수 있습니다.
new Map([...map].sort())
및 쉼표 키 값 키가 모두 문자열인 경우 스퀴드와 강제 콤마 joined 키 값 문자열을 비교합니다.'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]
위와 같은 정렬 함수에서, 또는 함수 인수에서 배열 파괴와 함께:
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]
그것은 동등한 것으로 취급되기 때문입니다.
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[Symbol.iterator] = function* () {
yield* [...map.entries()].sort((a, b) => a[0].localeCompare(b[0]));
}
반복기를 사용하면 한 번만 선언할 수 있다는 장점이 있습니다.지도에서 항목을 추가/삭제한 후, 지도 위에 새로운 for-loop이 반복기를 사용하여 이 변경 사항을 자동으로 반영합니다.위의 대부분의 답변과 같이 정렬된 복사본은 지도의 상태를 한 시점에만 반영하기 때문에 그렇지 않습니다.
사용자의 초기 상황을 사용한 전체적인 작업 예시입니다.
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
안부 전해요.
이 개념은 지도의 키를 배열로 추출하는 것입니다.배열을 정렬합니다.그런 다음 정렬된 배열을 반복하여 정렬되지 않은 맵에서 값 쌍을 가져와 새 맵에 넣습니다.새 지도는 순서대로 정렬됩니다.아래 코드는 이를 구현하는 것입니다.
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);
배열로 변환하고 배열 정렬 방법을 호출할 수 있습니다.
[...map].sort(/* etc */);
세부 사항을 파악하는데 2시간이 걸렸습니다.
질문에 대한 답변은 이미 https://stackoverflow.com/a/31159284/984471 에 나와 있습니다.
하지만 이 질문에는 보통의 것이 아닌 열쇠가 있습니다.
설명과 함께 명확하고 일반적인 예를 제시하면 다음과 같습니다.
- 여기 몇 가지 예시: https://javascript.info/map-set
- 아래 코드를 다음 링크로 복사 paste하여 특정 사용 사례에 맞게 수정할 수 있습니다. https://www.jdoodle.com/execute-nodejs-online/
.
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
도움이 되길 바랍니다.
안타깝게도 ES6에서는 실제로 구현되지 않았습니다.이 기능은 불변의 OrderedMap.sort()에 있습니다.Lodash에서 JS 또는 _.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 객체 지도였기 때문에 localCompare 함수를 사용했습니다.
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'}];
지도 객체를 정렬하지 않고 지도를 수행하기 전에 미리 정렬을 준비하는 것이 더 현실적인 예일 수 있습니다.이렇게 하면 실제로 구문이 상당히 압축됩니다.이렇게 맵 기능 전 정렬 기능을 적용할 수 있고 맵 전 정렬 기능을 적용할 수 있습니다(JSX 구문을 사용하여 작업 중인 리액트 앱의 예).
여기서 API에서 가져온 배열에 있는 자바스크립트 객체의 속성에 대해 작으면 -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>
)
현재 지도를 제대로 정렬할 수 없는 것으로 알고 있습니다.
맵을 배열로 변환하고 이렇게 정렬하는 다른 솔루션에는 다음과 같은 버그가 있습니다.
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}
정렬하면 새 개체가 생성되고 정렬되지 않은 개체에 대한 다른 모든 포인터가 끊어집니다.
약간의 변형 - 확산 구문이 없어서 작업을 하고 싶었습니다.object
대신에Map
.
Object.fromEntries(Object.entries(apis).sort())
Map()을 감소시켜 정렬하는 기능이 있습니다.
function groupBy(list, keyGetter) {
const map = new Map();
list.forEach((item) => {
const key = keyGetter(item);
const collection = map.get(key);
if (!collection) {
map.set(key, [item]);
} else {
collection.push(item);
}
});
const sortedMap = new Map();
[...map].sort((a, b) => b[1].length - a[1].length).forEach(e => sortedMap.set(e[0], e[1]));
return sortedMap;
}
const test = groupBy(array, item => item.fieldName);
언급URL : https://stackoverflow.com/questions/31158902/is-it-possible-to-sort-a-es6-map-object
'bestsource' 카테고리의 다른 글
WooCommerce | Variable Product | 값당 Attribute X(out Y)에 동일한 이미지 할당 (0) | 2023.10.21 |
---|---|
HTML 태그를 제거하지만 내부 HTML은 유지합니다. (0) | 2023.10.21 |
web.config가 원하는 길이의 요청을 허용하도록 구성하는 방법 (0) | 2023.10.21 |
SQL 대신 XML을 언제 사용합니까? (0) | 2023.10.21 |
각도 물질에 다중 선택 옵션을 구현하려면 어떻게 해야 합니까? (0) | 2023.10.21 |