जावास्क्रिप्ट - एक और सरणी के आधार पर सॉर्ट सरणी


168

क्या इस तरह दिखने वाले एक सरणी को सॉर्ट और पुनर्व्यवस्थित करना संभव है:

itemsArray = [ 
    ['Anne', 'a'],
    ['Bob', 'b'],
    ['Henry', 'b'],
    ['Andrew', 'd'],
    ['Jason', 'c'],
    ['Thomas', 'b']
]

इस सरणी की व्यवस्था से मेल खाने के लिए:

sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]

दुर्भाग्य से, मेरे पास ट्रैक रखने के लिए कोई आईडी नहीं है। मुझे आइटम्स को प्राथमिकता देने की आवश्यकता होगी- सॉर्टिंग को जितना संभव हो उतना करीब से मिलान करने के लिए।

अपडेट करें:

यहाँ उत्पादन मैं देख रहा हूँ:

itemsArray = [    
    ['Bob', 'b'],
    ['Jason', 'c'],
    ['Henry', 'b'],
    ['Thomas', 'b']
    ['Anne', 'a'],
    ['Andrew', 'd'],
]

किसी भी विचार यह कैसे किया जा सकता है?


यदि आप मैन्युअल रूप से सब कुछ नहीं करना चाहते हैं, तो सरणी फ़ंक्शन पाप PHP.js पर एक नज़र डालें
आदि

केवल sortingArray से अधिक पाशन और पुनर्लेखन itemsArray द्वारा
mplungjan

6
जहाँ कई सरणियों का समान छंटनी मान (यानी 'b') होता है, आप कैसे तय करते हैं कि छांटे गए सरणी में कौन सी वस्तु कहाँ जाती है? 'बॉब', 'हेनरी' और 'थॉमस' के साथ, जिनका मूल्य 'बी' है - आप कैसे तय करते हैं कि कौन पहले, तीसरे और चौथे स्थान पर जाता है?
मिच सैचवेल

@ मिच में क्या बाएं से दाएं पढ़ने को प्राथमिकता देना संभव होगा? यह एक सच्चा सिरदर्द है, क्योंकि मेरे पास तुलना करने के लिए कोई आईडी नहीं है।
user1448892

बाएं से दाएं क्या आपको इसका मतलब है कि वे मूल आइटम में दिखाई देने वाले क्रम में हैं?
मिच साचवेल

जवाबों:


74

कुछ इस तरह:

items = [ 
    ['Anne', 'a'],
    ['Bob', 'b'],
    ['Henry', 'b'],
    ['Andrew', 'd'],
    ['Jason', 'c'],
    ['Thomas', 'b']
]

sorting = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
result = []

sorting.forEach(function(key) {
    var found = false;
    items = items.filter(function(item) {
        if(!found && item[1] == key) {
            result.push(item);
            found = true;
            return false;
        } else 
            return true;
    })
})

result.forEach(function(item) {
    document.writeln(item[0]) /// Bob Jason Henry Thomas Andrew
})

यहाँ एक छोटा कोड है, लेकिन यह sortingसरणी को नष्ट कर देता है :

result = items.map(function(item) {
    var n = sorting.indexOf(item[1]);
    sorting[n] = '';
    return [n, item]
}).sort().map(function(j) { return j[1] })

27
द्विघात जटिलता! इसे बड़ी मात्रा में डेटा के साथ आज़माएं ...
जूलियन रॉयर

6
@ thg435: जटिलता का "अनुकूलन" से बहुत कम लेना-देना है, जब तक कि डेटा की मात्रा छोटी होने की गारंटी नहीं है (जो कि यहां हो सकता है)।
जूलियन रॉयर

2
@georg जब डेटा संरचनाओं पर कार्य करने वाले एल्गोरिदम की जटिलता की बात आती है, तो द्विघात (या बदतर) जटिलताओं के साथ एल्गोरिदम का अनुकूलन कभी भी समय से पहले नहीं होता है और हमेशा आवश्यक होता है (जब तक कि आप निर्धारित नहीं कर सकते कि डेटा का आकार छोटा होने वाला है) । प्रदर्शन का अंतर परिमाण के क्रम में व्यक्त (काफी शाब्दिक) है।
Abion47

236

एक लाइन जवाब।

itemsArray.sort(function(a, b){  
  return sortingArr.indexOf(a) - sortingArr.indexOf(b);
});

10
इससे उत्परिवर्तन होगा itemsArray। प्रदर्शन की आवश्यकता के आधार पर, यह करना अधिक सुरक्षित होगा itemsArray.slice().sort(...)
सवेटायटो 19

1
सॉर्ट विधि एक सरणी वापस। डेवलपर.
mozilla.org/en-US/docs/Web/JavaScript/Reference/…

8
यह सरणी को वापस करता है, लेकिन यह जगह में भी सॉर्ट करता है और मूल को उत्परिवर्तित करता है।
mynameistechno

2
इसका वास्तविक उत्तर होना चाहिए
urmurmur

6
@ मोरवेल, यह इस उत्तर के कारण sortingArrहै जिसमें सभी मूल्यों को समाहित करने की आवश्यकता है itemsArray। यदि वे मौजूद नहीं हैं, तो फिक्स को सरणी के पीछे आइटम को धकेलना है sortingArr:allProducts.sort((product1, product2) => { const index1 = manualSort.indexOf(product1.id); const index2 = manualSort.indexOf(product2.id); return ( (index1 > -1 ? index1 : Infinity) - (index2 > -1 ? index2 : Infinity) ); });
फ्रेशोली

35

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

इसलिए अगर मैं समझता हूं कि आप जो उदाहरण दे रहे हैं वह सही है, तो आप कुछ ऐसा कर सकते हैं:

function sortFunc(a, b) {
  var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
  return sortingArr.indexOf(a[1]) - sortingArr.indexOf(b[1]);
}

itemsArray.sort(sortFunc);

3
यह काम नहीं करेगा, जिसके परिणामस्वरूप आदेश बी, बी, बी, सी, सी, डी होगा जैसा indexOfकि पहला सूचकांक देता है।
मिच साचवेल

धन्यवाद, लेकिन मैं वस्तुओं के उत्पादन को पसंद करूंगा।
user1448892

6
मैं इस उत्तर को पसंद करता हूं यदि "आईडी" sortingArrअद्वितीय हैं - जो, शुक्र है, वे मेरे मामले में हैं :)
dillondrenzek

3
आपको sortingArrayप्रत्येक छँटाई पुनरावृत्ति पर इसे पुनः घोषित करने के लिए फ़ंक्शन के बाहर की घोषणा करनी चाहिए
aurumpotestasest

26

केस 1: मूल प्रश्न (पुस्तकालय नहीं)

अन्य उत्तर जो काम करते हैं। :)

केस 2: मूल प्रश्न (Lodash.js या Underscore.js)

var groups = _.groupBy(itemArray, 1);
var result = _.map(sortArray, function (i) { return groups[i].shift(); });

केस 3: एरियर को क्रमबद्ध करें जैसे कि यह एरे 2 था

मैं अनुमान लगा रहा हूं कि ज्यादातर लोग यहां PHP के array_multisort (मैंने किया था) के बराबर की तलाश में आए थे, इसलिए मुझे लगा कि मैं उस उत्तर को भी पोस्ट करूंगा। कुछ विकल्प हैं:

1. array_multisort () का मौजूदा JS कार्यान्वयन है । टिप्पणियों में इसे इंगित करने के लिए @ अदनान का धन्यवाद। हालांकि यह बहुत बड़ा है।

2. अपना लिखो। ( JSFiddle डेमो )

function refSort (targetData, refData) {
  // Create an array of indices [0, 1, 2, ...N].
  var indices = Object.keys(refData);

  // Sort array of indices according to the reference data.
  indices.sort(function(indexA, indexB) {
    if (refData[indexA] < refData[indexB]) {
      return -1;
    } else if (refData[indexA] > refData[indexB]) {
      return 1;
    }
    return 0;
  });

  // Map array of indices to corresponding values of the target array.
  return indices.map(function(index) {
    return targetData[index];
  });
}

3. Lodash.js या Underscore.js (प्रदर्शन पर ध्यान केंद्रित करने वाले दोनों लोकप्रिय, छोटे पुस्तकालय) सहायक कार्य प्रदान करते हैं जो आपको ऐसा करने की अनुमति देते हैं:

    var result = _.chain(sortArray)
      .pairs()
      .sortBy(1)
      .map(function (i) { return itemArray[i[0]]; })
      .value();

... जो (1) [index, value]जोड़े में SortArray को समूह में रखेगा , (2) उन्हें मान से क्रमबद्ध करें (आप यहां कॉलबैक भी प्रदान कर सकते हैं), (3) आइटम में से प्रत्येक जोड़े को आइटम से बदलें। जोड़ी से उत्पन्न हुआ।


1
उत्कृष्ट समाधान, वैकल्पिक रूप से आप _.indexBy का उपयोग कर सकते हैं और शिफ्ट को हटा सकते हैं यदि आपकी डेटा संरचना थोड़ी अधिक जटिल है
फ्रोजनफायर

20

यह शायद बहुत देर हो चुकी है लेकिन, आप ES6 शैली में नीचे दिए गए कोड के कुछ संशोधित संस्करण का भी उपयोग कर सकते हैं। यह कोड सरणियों के लिए है:

var arrayToBeSorted = [1,2,3,4,5];
var arrayWithReferenceOrder = [3,5,8,9];

वास्तविक ऑपरेशन:

arrayToBeSorted = arrayWithReferenceOrder.filter(v => arrayToBeSorted.includes(v));

ES5 में वास्तविक ऑपरेशन:

arrayToBeSorted = arrayWithReferenceOrder.filter(function(v) {
    return arrayToBeSorted.includes(v);
});

में परिणाम होना चाहिए arrayToBeSorted = [3,5]

संदर्भ सरणी को नष्ट नहीं करता है।


4
क्या होगा यदि मैं arrayToBeSorted वस्तुओं का एक सरणी है: {1: {…}, 2: {…}, 3: {…}, 4: {…}, 5: {…}}? लेकिन arrayWithReferenceOrder सिर्फ एक सामान्य सरणी है?
क्रिस्टल

3
@ सुश्रुत कैसे इस सरणी को सॉर्ट करता है?
hitautodestruct

@ क्रिस्टल, यह एक वस्तु है, वस्तुओं की एक सरणी नहीं। किसी वस्तु में तत्वों / वस्तुओं का कोई क्रम नहीं है, अर्थात उनका क्रम निर्धारित नहीं है। वस्तुओं की एक सरणी कुछ इस तरह दिखेगा [{name: "1"}, {name: "2"}, {name: "3"}, ...]
जॉन

8

मैं एक मध्यस्थ वस्तु ( itemsMap) का उपयोग करेगा , इस प्रकार द्विघात जटिलता से बचना होगा:

function createItemsMap(itemsArray) { // {"a": ["Anne"], "b": ["Bob", "Henry"], …}
  var itemsMap = {};
  for (var i = 0, item; (item = itemsArray[i]); ++i) {
    (itemsMap[item[1]] || (itemsMap[item[1]] = [])).push(item[0]);
  }
  return itemsMap;
}

function sortByKeys(itemsArray, sortingArr) {
  var itemsMap = createItemsMap(itemsArray), result = [];
  for (var i = 0; i < sortingArr.length; ++i) {
    var key = sortingArr[i];
    result.push([itemsMap[key].shift(), key]);
  }
  return result;
}

Http://jsfiddle.net/eUskE/ देखें


6
var sortedArray = [];
for(var i=0; i < sortingArr.length; i++) {
    var found = false;
    for(var j=0; j < itemsArray.length && !found; j++) {
        if(itemsArray[j][1] == sortingArr[i]) {
            sortedArray.push(itemsArray[j]);
            itemsArray.splice(j,1);
            found = true;
        }
    }
}

http://jsfiddle.net/s7b2P/

परिणामी क्रम: बॉब, जेसन, हेनरी, थॉमस, ऐनी, एंड्रयू


6

कुछ पसंद क्यों नहीं

//array1: array of elements to be sorted
//array2: array with the indexes

array1 = array2.map((object, i) => array1[object]);

मानचित्र फ़ंक्शन सभी संस्करणों पर उपलब्ध नहीं हो सकता है Javascript


1
यह सबसे साफ समाधान है, और इसका उत्तर स्वीकार किया जाना चाहिए। धन्यवाद!
न्यूमैन

3
let a = ['A', 'B', 'C' ]

let b = [3, 2, 1]

let c = [1.0, 5.0, 2.0]

// these array can be sorted by sorting order of b

const zip = rows => rows[0].map((_, c) => rows.map(row => row[c]))

const sortBy = (a, b, c) => {
  const zippedArray = zip([a, b, c])
  const sortedZipped = zippedArray.sort((x, y) => x[1] - y[1])

  return zip(sortedZipped)
}

sortBy(a, b, c)

2
कृपया एक संक्षिप्त विवरण / विवरण जोड़ने पर विचार करें कि यह कोड क्यों / कैसे प्रश्न का उत्तर देता है।
यनीस

3

यह वही है जिसकी मैं तलाश कर रहा था और मैंने एक और ऐरे के आधार पर एरे के अर्रे को छाँटने के लिए किया था:

यह ^ 3 पर है और सबसे अच्छा अभ्यास नहीं हो सकता है (ES6)

function sortArray(arr, arr1){
      return arr.map(item => {
        let a = [];
        for(let i=0; i< arr1.length; i++){
          for (const el of item) {
            if(el == arr1[i]){
              a.push(el);
            }   
            }
          }
          return a;
      });
    }
    
    const arr1 = ['fname', 'city', 'name'];
  const arr = [['fname', 'city', 'name'],
  ['fname', 'city', 'name', 'name', 'city','fname']];
  console.log(sortArray(arr,arr1));
यह किसी की मदद कर सकता है


2

मुझे यह एक JSON पेलोड के लिए करना था जो मुझे एक एपीआई से प्राप्त हुआ था, लेकिन यह उस क्रम में नहीं था जैसा मैं चाहता था।

एरे संदर्भ सरणी के रूप में, जिसको आप चाहते हैं कि दूसरा एरे को क्रमबद्ध करें:

var columns = [
    {last_name: "last_name"},
    {first_name: "first_name"},
    {book_description: "book_description"},
    {book_id: "book_id"},
    {book_number: "book_number"},
    {due_date: "due_date"},
    {loaned_out: "loaned_out"}
];

मैंने इन्हें वस्तुओं के रूप में किया क्योंकि इनमें अन्य गुण होंगे।

बनाया गया सरणी:

 var referenceArray= [];
 for (var key in columns) {
     for (var j in columns[key]){
         referenceArray.push(j);
     }
  }

डेटाबेस से सेट परिणाम के साथ इसका इस्तेमाल किया। मुझे नहीं पता कि यह कितना कुशल है, लेकिन मेरे द्वारा उपयोग किए जाने वाले कुछ स्तंभों के साथ, इसने ठीक काम किया।

result.forEach((element, index, array) => {                            
    var tr = document.createElement('tr');
    for (var i = 0; i < referenceArray.length - 1; i++) {
        var td = document.createElement('td');
        td.innerHTML = element[referenceArray[i]];
        tr.appendChild(td);

    }
    tableBody.appendChild(tr);
}); 

2

एक नया ऑर्डर किया गया सरणी प्राप्त करने के लिए, आप Mapएक सरणी में वांछित कुंजी के साथ सभी आइटम ले सकते हैं और एकत्र कर सकते हैं और वांछित समूह के तत्व को हटाकर वांछित आदेशित कुंजी को मैप कर सकते हैं।

var itemsArray = [['Anne', 'a'], ['Bob', 'b'], ['Henry', 'b'], ['Andrew', 'd'], ['Jason', 'c'], ['Thomas', 'b']],
    sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ],
    map = itemsArray.reduce((m, a) => m.set(a[1], (m.get(a[1]) || []).concat([a])), new Map),
    result = sortingArr.map(k => (map.get(k) || []).shift());

console.log(result);


👏That's मेरे fav, मैं instead♂️ {}Map
Can के

2
let sortedOrder = [ 'b', 'c', 'b', 'b' ]
let itemsArray = [ 
    ['Anne', 'a'],
    ['Bob', 'b'],
    ['Henry', 'b'],
    ['Andrew', 'd'],
    ['Jason', 'c'],
    ['Thomas', 'b']
]
a.itemsArray(function (a, b) {
    let A = a[1]
    let B = b[1]

    if(A != undefined)
        A = A.toLowerCase()

    if(B != undefined)
        B = B.toLowerCase()

    let indA = sortedOrder.indexOf(A)
    let indB = sortedOrder.indexOf(B)

    if (indA == -1 )
        indA = sortedOrder.length-1
    if( indB == -1)
        indB = sortedOrder.length-1

    if (indA < indB ) {
        return -1;
    } else if (indA > indB) {
        return 1;
    }
    return 0;
})

यह समाधान वस्तुओं को अंत में जोड़ देगा यदि छँटाई कुंजी संदर्भ सरणी में मौजूद नहीं है


0

यह काम करना चाहिए:

var i,search, itemsArraySorted = [];
while(sortingArr.length) {
    search = sortingArr.shift();
    for(i = 0; i<itemsArray.length; i++) {
        if(itemsArray[i][1] == search) {
            itemsArraySorted.push(itemsArray[i]);
            break;
        }
    } 
}

itemsArray = itemsArraySorted;

0

आप इस विधि को आजमा सकते हैं।

const sortListByRanking = (rankingList, listToSort) => {
  let result = []

  for (let id of rankingList) {
    for (let item of listToSort) {
      if (item && item[1] === id) {
        result.push(item)
      }
    }
  }

  return result
}


0

यदि आपको यहां वस्तुओं की एक सरणी के साथ ऐसा करने की आवश्यकता है, तो यहां @Durgpal सिंह के भयानक उत्तर का अनुकूलन है:

const itemsArray = [
  { name: 'Anne', id: 'a' },
  { name: 'Bob', id: 'b' },
  { name: 'Henry', id: 'b' },
  { name: 'Andrew', id: 'd' },
  { name: 'Jason', id: 'c' },
  { name: 'Thomas', id: 'b' }
]

const sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]

Object.keys(itemsArray).sort((a, b) => {
  return sortingArr.indexOf(itemsArray[a].id) - sortingArr.indexOf(itemsArray[b].id);
})

-1

JQuery से $ .inArray () विधि का उपयोग करें। आप तब कुछ ऐसा कर सकते थे

var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
var newSortedArray = new Array();

for(var i=sortingArr.length; i--;) {
 var foundIn = $.inArray(sortingArr[i], itemsArray);
 newSortedArray.push(itemsArray[foundIn]);
}

-1

दो सरणियों के प्रतिच्छेदन का उपयोग करें।

उदाहरण के लिए:

var sortArray = ['a', 'b', 'c',  'd', 'e'];

var arrayToBeSort = ['z', 's', 'b',  'e', 'a'];

_.intersection(sortArray, arrayToBeSort) 

=> ['ए', 'बी', 'ई']

यदि 'z' और 's' पहली सरणी की सीमा से बाहर हैं, तो परिणाम के अंत में इसे जोड़ें


-4

आप ऐसा कुछ कर सकते हैं:

function getSorted(itemsArray , sortingArr ) {
  var result = [];
  for(var i=0; i<arr.length; i++) {
    result[i] = arr[sortArr[i]];
  }
  return result;
}

आप इसका परीक्षण यहां कर सकते हैं

नोट: यह मानता है कि आपके द्वारा पास किए जाने वाले सरणियों का आकार बराबर है, यदि ऐसा नहीं हो सकता है, तो आपको कुछ अतिरिक्त जांचों को जोड़ना होगा।

उल्लेख लिंक

उल्लेख


यह बुरी तरह से संपादन की जरूरत है। न केवल jfiddle गलत परिणाम लौटाता है, फ़ंक्शन तर्क नाम आंतरिक सामग्री से मेल नहीं खाते हैं?
ट्वोबॉब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.