bestsource

ES6 맵 객체를 정렬할 수 있습니까?

bestsource 2023. 10. 21. 10:37
반응형

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

반응형