Apakah mungkin untuk mengurutkan entri dari objek peta es6?
var map = new Map();
map.set('2-1', foo);
map.set('0-1', bar);
menghasilkan:
map.entries = {
0: {"2-1", foo },
1: {"0-1", bar }
}
Apakah mungkin untuk mengurutkan entri berdasarkan kuncinya?
map.entries = {
0: {"0-1", bar },
1: {"2-1", foo }
}
javascript
ecmascript-6
Ivan Bacher
sumber
sumber
Jawaban:
Menurut dokumentasi MDN:
Anda bisa melakukannya dengan cara ini:
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)
Menggunakan
.sort()
, ingatlah bahwa larik diurutkan sesuai dengan nilai poin kode Unicode setiap karakter, sesuai dengan konversi string dari setiap elemen. Jadi2-1, 0-1, 3-1
akan diurutkan dengan benar.sumber
var mapAsc = new Map([...map.entries()].sort((a,b) => a[0] > b[0]));
menggunakan fungsi panah (lambda)2-1,foo
dengan0-1,bar
dan3-1,baz
(a,b) => a[0] > b[0]
!...
titik yang penting jika Anda mencoba untuk mengurutkan MapIterator1e-9
diletakkan setelah100
di peta yang diurutkan. Kode yang berfungsi dengan angka:new Map([...map.entries()].sort((e1, e2) => e1[0] - e2[0]))
Jawaban singkat
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 ))
Misalnya, membandingkan string nilai, yang bisa sama, kita meneruskan fungsi sortir yang mengakses [1] dan memiliki kondisi sama dengan yang mengembalikan 0:
new Map([...map].sort((a, b) => (a[1] > b[1] && 1) || (a[1] === b[1] ? 0 : -1)))
Membandingkan string kunci, yang tidak bisa sama (kunci string identik akan menimpa satu sama lain), kita dapat melewati kondisi sama dengan. Namun, kita tetap harus secara eksplisit mengembalikan -1, karena mengembalikan lazy
a[0] > b[0]
salah memberikan false (diperlakukan sebagai 0, yaitu sama) ketikaa[0] < b[0]
:new Map([...map].sort((a, b) => a[0] > b[0] ? 1 : -1))
Secara detail dengan contoh
The
.entries()
dalam[...map.entries()]
(disarankan dalam banyak jawaban) berlebihan, mungkin menambahkan iterasi ekstra peta kecuali mengoptimalkan mesin JS yang pergi untuk Anda.Dalam kasus pengujian sederhana, Anda dapat melakukan apa yang diminta pertanyaan dengan:
new Map([...map].sort())
... yang, jika semua kuncinya adalah string, membandingkan string nilai kunci yang digabung dan dipaksakan seperti
'2-1,foo'
dan'0-1,[object Object]'
, menampilkan Peta baru dengan urutan penyisipan baru:Catatan: jika Anda hanya melihat
{}
di keluaran konsol SO, lihat di konsol browser Anda yang sebenarnyaconst map = new Map([ ['2-1', 'foo'], ['0-1', { bar: 'bar' }], ['3-5', () => 'fuz'], ['3-2', [ 'baz' ]] ]) console.log(new Map([...map].sort()))
NAMUN , bukanlah praktik yang baik untuk mengandalkan paksaan dan stringifikasi seperti ini. Anda bisa mendapatkan kejutan seperti:
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()) }
Bug seperti ini sangat sulit untuk di-debug - jangan ambil risiko!
Jika Anda ingin mengurutkan kunci atau nilai, yang terbaik adalah mengaksesnya secara eksplisit dengan
a[0]
danb[0]
dalam fungsi sortir, seperti ini. Perhatikan bahwa kita harus mengembalikan-1
dan1
untuk sebelum dan sesudah, bukanfalse
atau0
sebagai mentaha[0] > b[0]
karena itu diperlakukan sama: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)))
sumber
Konversikan
Map
ke array menggunakanArray.from
, urutkan array, konversi kembali keMap
, misalnyanew Map( Array .from(eventsByDate) .sort((a, b) => { // a[0], b[0] is the key of the map return a[0] - b[0]; }) )
sumber
[...map.values()].sort()
tidak berhasil untuk saya, tetapiArray.from(map.values()).sort()
berhasilIdenya adalah mengekstrak kunci peta Anda ke dalam array. Sortir larik ini. Kemudian lakukan iterasi pada larik yang diurutkan ini, dapatkan pasangan nilainya dari peta yang tidak disortir dan masukkan ke dalam peta baru. Peta baru akan diurutkan. Kode di bawah ini adalah implementasinya:
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);
sumber
unsortedMap.keys()
. Jugakeys.sort().map...
haruskeys.sort().forEach...
.Anda dapat mengonversi ke array dan memanggil metode penyortiran array di atasnya:
[...map].sort(/* etc */);
sumber
Sayangnya, tidak benar-benar diterapkan di ES6. Anda memiliki fitur ini dengan OrderedMap.sort () dari ImmutableJS atau _.sortBy () dari Lodash.
sumber
Salah satu caranya adalah dengan mendapatkan array entri, mengurutkannya, dan kemudian membuat Map baru dengan array yang diurutkan:
let ar = [...myMap.entries()]; sortedArray = ar.sort(); sortedMap = new Map(sortedArray);
Tetapi jika Anda tidak ingin membuat objek baru, tetapi mengerjakan objek yang sama, Anda dapat melakukan sesuatu seperti ini:
// 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); })
sumber
Cuplikan di bawah ini mengurutkan peta yang diberikan berdasarkan kuncinya dan memetakan kembali kunci tersebut ke objek nilai kunci. Saya menggunakan fungsi localeCompare karena peta saya adalah 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; });
hasil:
[{t:'tt'}, {x:'xx'}, {y: 'yy'}];
sumber
Sejauh yang saya lihat, saat ini tidak mungkin mengurutkan Peta dengan benar.
Solusi lain di mana Peta diubah menjadi larik dan diurutkan dengan cara ini memiliki bug berikut:
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}
Penyortiran membuat objek baru dan semua petunjuk lain ke objek yang tidak diurutkan rusak.
sumber
2 jam dihabiskan untuk membahas detail.
Perhatikan bahwa jawaban untuk pertanyaan sudah diberikan di https://stackoverflow.com/a/31159284/984471
Namun, pertanyaannya memiliki kunci yang tidak biasa,
Contoh yang jelas & umum dengan penjelasan, di bawah ini memberikan beberapa kejelasan lagi:
.
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
Semoga membantu.
sumber
Mungkin contoh yang lebih realistis tentang tidak menyortir objek Peta tetapi mempersiapkan penyortiran di depan sebelum melakukan Peta. Sintaksnya menjadi cukup ringkas jika Anda melakukannya seperti ini. Anda dapat menerapkan pengurutan sebelum fungsi peta seperti ini, dengan fungsi pengurutan sebelum peta (Contoh dari aplikasi React yang saya kerjakan menggunakan sintaks JSX)
Tandai bahwa saya di sini mendefinisikan fungsi penyortiran di dalam menggunakan fungsi panah yang mengembalikan -1 jika lebih kecil dan 0 jika tidak diurutkan pada properti objek Javascript dalam larik yang saya dapatkan dari 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> )
sumber
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"}
sumber