क्या ES6 मैप ऑब्जेक्ट को सॉर्ट करना संभव है?


98

क्या 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 }
}

4
नक्शे स्वाभाविक रूप से क्रमबद्ध नहीं हैं (सिवाय पुनरावृत्त प्रविष्टि क्रम को छोड़कर, जिन्हें छांटने की आवश्यकता होती है और फिर [फिर से जोड़ना]।
user2864740

1
जब आप नक्शे पर पुनरावृति करते हैं, तो प्रविष्टियाँ क्रमबद्ध करें (अर्थात इसे एक सरणी में बदल दें)
हैलिसन

जवाबों:


139

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सही ढंग से हल किया जाएगा।


7
आप उस फंक्शन (ए, बी) स्टफ्स को छोटा कर सकते हैं: var mapAsc = new Map([...map.entries()].sort((a,b) => a[0] > b[0]));एरो फंक्शन (लैम्ब्डा) का उपयोग करके
जिमी चंद्रा

2
वास्तव में, यह तीक्ष्ण रूप से तुलना 2-1,fooकरता है 0-1,barऔर3-1,baz
Bergi


3
...डॉट्स महत्वपूर्ण अन्यथा आप एक MapIterator सॉर्ट करने के लिए कोशिश कर रहे हैं कर रहे हैं
muttonUp

2
यदि मानचित्र कुंजियाँ संख्याएँ हैं, तो आपको क्रमांकित मानचित्र में 1e-9डालने के बाद संख्याओं के साथ अमान्य परिणाम मिलेंगे 100। कोड जो संख्याओं के साथ काम करता है:new Map([...map.entries()].sort((e1, e2) => e1[0] - e2[0]))
cdalxndr

58

संक्षिप्त जवाब

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

प्रमुख तारों की तुलना करना, जो समान नहीं हो सकते हैं (समान स्ट्रिंग कुंजी एक दूसरे को अधिलेखित कर देंगे), हम बराबर स्थिति को छोड़ सकते हैं। हालाँकि, हमें अभी भी स्पष्ट रूप से -1 लौटाना चाहिए, क्योंकि एक आलसी को a[0] > b[0]गलत तरीके से लौटाने से गलत (0 के बराबर माना जाता है), जब a[0] < b[0]:

 new Map([...map].sort((a, b) => a[0] > b[0] ? 1 : -1))

उदाहरणों के साथ विस्तार से

.entries()में[...map.entries()] (कई जवाब में सुझाव दिया) शायद मानचित्र जब तक जे एस इंजन अनुकूलन है कि दूर आप के लिए की एक अतिरिक्त यात्रा जोड़ने बेमानी है।

सरल परीक्षण के मामले में, आप वह कर सकते हैं जो प्रश्न के साथ पूछता है:

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


11
क्या जवाब है, हम एसओ खोज तंत्र को ठीक करेंगे। यह अच्छा कुछ यहाँ खोना नहीं चाहिए।
सेराओसे

30

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

1
[...map.values()].sort()मेरे लिए काम नहीं किया, लेकिन Array.from(map.values()).sort()किया
रोब Juurlink

1
यह वास्तव में मेरी मदद करता था, बिना Array.from के, टाइपस्क्रिप्ट ने मुझे एक जटिल त्रुटि दी।
icSapper

7

विचार आपके नक्शे की कुंजियों को एक सरणी में निकालने का है। इस सरणी को सॉर्ट करें। फिर इस क्रमबद्ध सरणी पर पुनरावृत्त करें, अपने मूल्य जोड़े को अनसोल्ड मैप से प्राप्त करें और उन्हें नए मानचित्र में डालें। नया नक्शा क्रमबद्ध क्रम में होगा। नीचे दिया गया कोड यह कार्यान्वयन है:

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

2
अनसुनी कुंजी को केवल उपयोग करके निर्धारित किया जा सकता है unsortedMap.keys()। भी keys.sort().map...होना चाहिए keys.sort().forEach...
faintsignal

5

आप एक सरणी में परिवर्तित कर सकते हैं और उस पर सरणी स्रोत कॉलिंग कर सकते हैं:

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

3
और क्या? आपको एक सारणी मिलती है जिसमें मानचित्र या वस्तु नहीं होती है
ग्रीन

5
और आप कुंजी खो देते हैं
braks


3

एक तरीका यह है कि प्रविष्टियाँ सरणी प्राप्त करें, इसे क्रमबद्ध करें, और फिर क्रमबद्ध सरणी के साथ एक नया मानचित्र बनाएँ:

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

1

नीचे दिए गए स्निपेट इसकी कुंजियों द्वारा दिए गए नक्शे को देखते हैं और कुंजी को फिर से कुंजी-मूल्य ऑब्जेक्ट में मैप करते हैं। मैंने अपने मानचित्र का स्ट्रिंग-> स्ट्रिंग ऑब्जेक्ट मैप होने के बाद से मैंने 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'}];


1

जहाँ तक मैं देख रहा हूँ कि वर्तमान में मानचित्र को ठीक से छांटना संभव नहीं है।

अन्य समाधान जहां मानचित्र को एक सरणी में परिवर्तित किया जाता है और इस प्रकार क्रमबद्ध किया जाता है, उसमें निम्न बग होते हैं:

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}

सॉर्टिंग एक नई ऑब्जेक्ट बनाता है और अनसोल्ड ऑब्जेक्ट को अन्य सभी पॉइंटर्स टूट जाते हैं।


1

विवरण में लाने के लिए 2 घंटे का समय।

ध्यान दें कि प्रश्न का उत्तर पहले से ही https://stackoverflow.com/a/31159284/984471 पर दिया गया है

हालाँकि, इस प्रश्न की कुंजी है जो सामान्य नहीं हैं, स्पष्टीकरण के साथ
एक स्पष्ट और सामान्य उदाहरण, नीचे है जो कुछ और स्पष्टता प्रदान करता है:

  • कुछ और उदाहरण यहाँ: https://javascript.info/map-set
  • आप नीचे दिए गए कोड को निम्न लिंक पर कॉपी-पेस्ट कर सकते हैं, और इसे अपने विशिष्ट उपयोग के मामले में संशोधित कर सकते हैं: 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

उम्मीद है की वो मदद करदे।


0

मैप ऑब्जेक्ट को न छांटने के बारे में शायद अधिक यथार्थवादी उदाहरण है लेकिन मैप करने से पहले छंटाई को तैयार करना। सिंटैक्स वास्तव में बहुत कॉम्पैक्ट हो जाता है अगर आप इसे इस तरह से करते हैं। आप इस तरह से मानचित्र समारोह से पहले छँटाई को लागू कर सकते हैं, मानचित्र से पहले एक प्रकार्य फ़ंक्शन के साथ (उदाहरण एक प्रतिक्रिया ऐप से मैं जेएसएक्स सिंटैक्स का उपयोग करके काम कर रहा हूं)

चिह्नित करें कि मैं यहां एक तीर फ़ंक्शन का उपयोग करके एक छँटाई फ़ंक्शन को परिभाषित करता हूं जो -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>
                    )

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

3
हालांकि यह लेखकों के सवाल का जवाब दे सकता है, लेकिन इसमें कुछ स्पष्ट शब्दों और प्रलेखन के लिंक का अभाव है। इसके आसपास कुछ वाक्यांशों के बिना रॉ कोड स्निपेट्स बहुत उपयोगी नहीं हैं। कृपया अपना उत्तर संपादित करें।
नरक

2
साथ ही, यह 3 साल पुराना सवाल है। आपको क्या लगता है कि आपका उत्तर बताता है कि अन्य उत्तर पहले से ही कवर नहीं किए गए हैं?
नरक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.