Nice programing

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

nicepro 2021. 1. 9. 11:39
반응형

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 문서에 따르면 :

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올바르게 정렬됩니다.


변환 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];
    })
)

짧은 대답

 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)))


The idea is to extract the keys of your map into an array. Sort this array. Then iterate over this sorted array, get its value pair from the unsorted map and put them into a new map. The new map will be in sorted order. The code below is it's implementation:

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);

Unfortunately, not really implemented in ES6. You have this feature with OrderedMap.sort() from ImmutableJS or _.sortBy() from Lodash.


You can convert to an array and call array soring methods on it:

[...map].sort(/* etc */);

One way is to get the entries array, sort it, and then create a new Map with the sorted array:

let ar = [...myMap.entries()];
sortedArray = ar.sort();
sortedMap = new Map(sortedArray);

But if you don't want to create a new object, but to work on the same one, you can do something like this:

// 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);
})

The snippet below sorts given map by its keys and maps the keys to key-value objects again. I used localeCompare function since my map was string->string object map.

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'}];


Perhaps a more realistic example about not sorting a Map object but preparing the sorting up front before doing the Map. The syntax gets actually pretty compact if you do it like this. You can apply the sorting before the map function like this, with a sort function before map (Example from a React app I am working on using JSX syntax)

Mark that I here define a sorting function inside using an arrow function that returns -1 if it is smaller and 0 otherwise sorted on a property of the Javascript objects in the array I get from an API.

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"}

ReferenceURL : https://stackoverflow.com/questions/31158902/is-it-possible-to-sort-a-es6-map-object

반응형