किसी अन्य ऐरे के आधार पर कुंजियों द्वारा एक अर्रे को सॉर्ट करें?


153

क्या PHP में ऐसा कुछ करना संभव है? आप एक फ़ंक्शन लिखने के बारे में कैसे जाएंगे? यहाँ एक उदाहरण है। आदेश सबसे महत्वपूर्ण चीज है।

$customer['address'] = '123 fake st';
$customer['name'] = 'Tim';
$customer['dob'] = '12/08/1986';
$customer['dontSortMe'] = 'this value doesnt need to be sorted';

और मैं कुछ ऐसा करना चाहूंगा

$properOrderedArray = sortArrayByArray($customer, array('name', 'dob', 'address'));

क्योंकि अंत में मैं एक फॉर्च्यूनर () का उपयोग करता हूं और वे सही क्रम में नहीं होते हैं (क्योंकि मैं उन मानों को एक स्ट्रिंग में जोड़ता हूं, जिन्हें सही क्रम में होना चाहिए और मुझे अग्रिम में सभी सरणी कुंजियों का पता नहीं है / मान)।

मैंने PHP के आंतरिक सरणी फ़ंक्शन के माध्यम से देखा है, लेकिन ऐसा लगता है कि आप केवल वर्णानुक्रम या संख्यात्मक रूप से सॉर्ट कर सकते हैं।

जवाबों:


347

बस का उपयोग करें array_mergeया array_replaceArray_mergeआपके द्वारा दिए गए सरणी के साथ शुरू करके (उचित क्रम में) और आपके वास्तविक सरणी से डेटा के साथ कुंजी को अधिलेखित / जोड़कर काम करता है:

$customer['address'] = '123 fake st';
$customer['name'] = 'Tim';
$customer['dob'] = '12/08/1986';
$customer['dontSortMe'] = 'this value doesnt need to be sorted';

$properOrderedArray = array_merge(array_flip(array('name', 'dob', 'address')), $customer);
//Or:
$properOrderedArray = array_replace(array_flip(array('name', 'dob', 'address')), $customer);

//$properOrderedArray -> array('name' => 'Tim', 'address' => '123 fake st', 'dob' => '12/08/1986', 'dontSortMe' => 'this value doesnt need to be sorted')

पीएस - मैं इस 'बासी' सवाल का जवाब दे रहा हूं, क्योंकि मुझे लगता है कि पिछले उत्तर के रूप में दिए गए सभी लूप ओवरकिल हैं।


31
यह अच्छी तरह से काम करता है अगर आपके पास स्ट्रिंग कुंजियाँ हैं, लेकिन संख्यात्मक के लिए नहीं। PHP डॉक्स: "यदि इनपुट सरणियों में समान स्ट्रिंग कुंजियाँ हैं, तो उस कुंजी के लिए बाद का मान पिछले वाले को अधिलेखित कर देगा। यदि, हालांकि, सरणियों में संख्यात्मक कुंजियाँ हैं, तो बाद में मान मूल मान को अधिलेखित नहीं करेगा, लेकिन होगा। संलग्न। "
bolbol

7
अच्छा है, लेकिन अगर मूल्यों में मौजूद नहीं हैं तो क्या होगा? मुझे इसकी आवश्यकता है, लेकिन केवल अगर किसी भी कुंजी का अस्तित्व है ... संभवतः उस पर फिर से एक प्रक्षालित करने की आवश्यकता है ...
सोलोमन क्लॉसन

5
मेरे मामले के लिए यह array_merge के बजाय array_replace है। array_merge दिए गए कुंजियों में दूसरी सरणी को बदलने के बजाय दोनों मानों को मिलाएं।
नवफोरको

3
मैंने कुछ साल पहले कुछ अलग खोजते हुए आपके समाधान पर ठोकर खाई थी - और मैंने खुद को सोचा, यह छोरों की तुलना में बेहद कुशल है। अब मुझे आपके समाधान की आवश्यकता है और इसे फिर से खोजने में मुझे एक घंटे का समय लगा! धन्यवाद!
माइकल

4
इसके अतिरिक्त, यदि 'ऑर्डर' एरे (यानी, एरे ('नेम', 'डोब', 'एड्रेस')) में एरियर को सॉर्ट करने की तुलना में अधिक कीज़ हैं, तो ऑरिजनल सरणी के साथ परिणामी सॉर्ट किए गए एरे का अतिरिक्त array_intersect कट जाएगा। आवारा चाबियाँ जिन्हें array_merge पर जोड़ा गया था।
bbe

105

तुम वहाँ जाओ:

function sortArrayByArray(array $array, array $orderArray) {
    $ordered = array();
    foreach ($orderArray as $key) {
        if (array_key_exists($key, $array)) {
            $ordered[$key] = $array[$key];
            unset($array[$key]);
        }
    }
    return $ordered + $array;
}

12
तो आप + संकेत के साथ 2 सरणियों में शामिल हो सकते हैं? मुझे कभी नहीं पता था कि, मैं उपयोग कर रहा हूँ array_merge()!
एलेक्स

3
क्या यह उपयोग करने से बेहतर है usort()या uasort()?
19

5
breakमान मिलने के बाद आपको एक स्टेटमेंट डालना चाहिए ।
Adel

4
जब आप array_merge()सरणी +ऑपरेटर के साथ प्रतिस्थापित करते हैं तो @alex बहुत सावधान रहें । यह कुंजी द्वारा (संख्यात्मक कुंजियों के लिए भी) और बाएं से दाएं में array_mergeविलय होता है , जबकि दाएं से बाएं से विलय होता है और कभी भी संख्यात्मक कुंजी को अधिलेखित नहीं करता है। जैसे [0,1,2]+[0,5,6,7] = [0,1,2,7]समय array_merge([0,1,2],[0,5,6,7]) = [0,1,2,0,5,6,7]और ['a' => 5] + ['a' => 7] = ['a' => 5]पर array_merge(['a' => 5], ['a' => 7]) = ['a' => 7]
फ्लू

क्या +संकेत का उपयोग करना सुरक्षित है ?
कांपिको

47

कैसे इस समाधान के बारे में

$order = array(1,5,2,4,3,6);

$array = array(
    1 => 'one',
    2 => 'two',
    3 => 'three',
    4 => 'four',
    5 => 'five',
    6 => 'six'
);

uksort($array, function($key1, $key2) use ($order) {
    return (array_search($key1, $order) > array_search($key2, $order));
});

1
यह एक और अधिक upvotes की जरूरत है, अन्य काम नहीं किया / अच्छा काम नहीं करते हैं जबकि यह मेरे मामले में ठीक चलता है।
एनजी सेक लॉन्ग अप

यह बहुत कुशल नहीं है। हर तुलना के लिए, सरणी में दो रैखिक खोजों का प्रदर्शन किया जाता है। यदि हम uksort () होने के समय की जटिलता को मानते हैं O(n * log n), तो यह एल्गोरिथ्म चलता है O(n^2 * log(n))
TheOperator

36

PHP> = 5.3.0 के लिए एक और तरीका:

$customer['address'] = '123 fake st';
$customer['name'] = 'Tim';
$customer['dob'] = '12/08/1986';
$customer['dontSortMe'] = 'this value doesnt need to be sorted';

$customerSorted = array_replace(array_flip(array('name', 'dob', 'address')), $customer);

परिणाम:

Array (
  [name] => Tim
  [dob] => 12/08/1986
  [address] => 123 fake st
  [dontSortMe] => this value doesnt need to be sorted
)

स्ट्रिंग और संख्यात्मक कुंजियों के साथ ठीक काम करता है।


2
+ जबकि वे दोनों काम करते हैं, मुझे array_replace()इरादे से बेहतर रिले करने के लिए मिला array_merge()
जेसन मैकक्रेरी

1
array_replaceचर प्रकार को भी बरकरार रखता है। यदि आपके सरणी में कोई मान होता है (string) '1'और आप +ऑपरेटर का उपयोग करते थे , तो मान को बदल दिया जाता था(int) 1
halfpastfour.am

1
यह संख्यात्मक कुंजियों पर भी काम करता है ( array_merge()बस उन्हें जोड़ देगा?)। तर्क यहाँ बहुत अच्छी तरह से समझाया गया हैसबसे पहले , array_flip()$ क्रम सरणी के मानों को कुंजियों में बदलता है। दूसरा , array_replace()पहले सरणी के मूल्यों को दूसरे सरणी में समान कुंजी वाले मानों के साथ बदलता है। यदि आपको किसी अन्य से कुंजियों के अनुसार सरणी को क्रमबद्ध करने की आवश्यकता है, तो आपको उपयोग करने की आवश्यकता नहीं है array_flip
aexl

23
function sortArrayByArray(array $toSort, array $sortByValuesAsKeys)
{
    $commonKeysInOrder = array_intersect_key(array_flip($sortByValuesAsKeys), $toSort);
    $commonKeysWithValue = array_intersect_key($toSort, $commonKeysInOrder);
    $sorted = array_merge($commonKeysInOrder, $commonKeysWithValue);
    return $sorted;
}

14

अपने आदेश के अनुसार एक सरणी लें:

$order = array('north', 'east', 'south', 'west');

आप array_intersectडॉक्स का उपयोग करके मूल्यों के आधार पर एक और सरणी को सॉर्ट कर सकते हैं :

/* sort by value: */
$array = array('south', 'west', 'north');
$sorted = array_intersect($order, $array);
print_r($sorted);

या आपके मामले में, कुंजियों के आधार पर, array_intersect_keyडॉक्स का उपयोग करें :

/* sort by key: */
$array = array_flip($array);
$sorted = array_intersect_key(array_flip($order), $array);
print_r($sorted);

दोनों फ़ंक्शन पहले पैरामीटर के क्रम को बनाए रखेंगे और केवल दूसरे ऐरे से मान (या कुंजियाँ) लौटाएंगे।

इसलिए इन दो मानक मामलों के लिए आपको छँटाई / पुनः व्यवस्था करने के लिए अपने आप पर एक फ़ंक्शन लिखने की आवश्यकता नहीं है।


इंटरसेक्ट को उन प्रविष्टियों से छुटकारा मिल जाएगा जिन्हें वह पहले से नहीं जानता है।
डैनमैन

1
यह कुंजी द्वारा छँटाई के लिए गलत है। array_intersect_key केवल array1 से मान लौटाएगा, नहीं array2
डरावना

Pavsid के साथ सहमत - array_intersect_key उदाहरण गलत है - यह पहले सरणी से मान लौटाता है, दूसरा नहीं।
जोनाथन Aquino

10

मैं Darkwaltz4 के समाधान का उपयोग करता हूं , लेकिन array_fill_keysइसके बजाय इसका उपयोग किया जाता है array_flipताकि NULLकोई कुंजी सेट न हो $array

$properOrderedArray = array_replace(array_fill_keys($keys, null), $array);

5

बिना जादू के ...

$array=array(28=>c,4=>b,5=>a);
$seq=array(5,4,28);    
SortByKeyList($array,$seq) result: array(5=>a,4=>b,28=>c);

function sortByKeyList($array,$seq){
    $ret=array();
    if(empty($array) || empty($seq)) return false;
    foreach($seq as $key){$ret[$key]=$dataset[$key];}
    return $ret;
}

1
यह अच्छा धन्यवाद काम करता है, बस $datasetपैरामीटर नाम से मेल करने के लिए अद्यतन
kursus

3

यदि आपके पास सरणी में सरणी है, तो आपको एरन द्वारा फ़ंक्शन को थोड़ा बदलना होगा ...

function sortArrayByArray($array,$orderArray) {
    $ordered = array();
    foreach($orderArray as $key => $value) {
        if(array_key_exists($key,$array)) {
                $ordered[$key] = $array[$key];
                unset($array[$key]);
        }
    }
    return $ordered + $array;
}

2

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

function array_sub_sort(array $values, array $keys){
    $keys = array_flip($keys);
    return array_merge(array_intersect_key($keys, $values), array_intersect_key($values, $keys));
}

उदाहरण:

$array_complete = [
    'a' => 1,
    'c' => 3,
    'd' => 4,
    'e' => 5,
    'b' => 2
];

$array_sub_sorted = array_sub_sort($array_complete, ['a', 'b', 'c']);//return ['a' => 1, 'b' => 2, 'c' => 3];

1

PHP के पास आपकी सहायता करने के लिए कार्य हैं:

$arrayToBeSorted = array('west', 'east', 'south', 'north');
$order = array('north', 'south', 'east', 'west');

// sort array
usort($arrayToBeSorted, function($a, $b) use ($order){
    // sort using the numeric index of the second array
    $valA = array_search($a, $order);
    $valB = array_search($b, $order);

    // move items that don't match to end
    if ($valA === false)
        return -1;
    if ($valB === false)
        return 0;

    if ($valA > $valB)
        return 1;
    if ($valA < $valB)
        return -1;
    return 0;
});

Usort आपके लिए सभी कार्य करता है और array_search कुंजी प्रदान करता है। array_search () तब गलत हो जाता है जब उसे कोई मेल नहीं मिल सकता है, ताकि जो आइटम सॉर्ट सरणी में नहीं हैं वे स्वाभाविक रूप से सरणी के निचले भाग में जाएं।

नोट: uasort () कुंजी => वेल्यू रिलेशनशिप को प्रभावित किए बिना एरे को ऑर्डर करेगा।


1
  • अनुरोध के अनुसार
  • int- कीज़ के लिए सेव करें (array_replace के कारण)
  • वापसी कुंजियाँ इनपुटअरे में मौजूद नहीं हैं
  • (वैकल्पिक रूप से) फ़िल्टर कुंजी दिए गए की-लिस्ट में मौजूद नहीं है

कोड:

 /**
 * sort keys like in key list
 * filter: remove keys are not listed in keyList
 * ['c'=>'red', 'd'=>'2016-12-29'] = sortAndFilterKeys(['d'=>'2016-12-29', 'c'=>'red', 'a'=>3 ]], ['c', 'd', 'z']){
 *
 * @param array $inputArray
 * @param string[]|int[] $keyList
 * @param bool $removeUnknownKeys
 * @return array
 */
static public function sortAndFilterKeys($inputArray, $keyList, $removeUnknownKeys=true){
    $keysAsKeys = array_flip($keyList);
    $result = array_replace($keysAsKeys, $inputArray); // result = sorted keys + values from input + 
    $result = array_intersect_key($result, $inputArray); // remove keys are not existing in inputArray 
    if( $removeUnknownKeys ){
        $result = array_intersect_key($result, $keysAsKeys); // remove keys are not existing in keyList 
    }
    return $result;
}

1

पहला सुझाव

function sortArrayByArray($array,$orderArray) {
    $ordered = array();
    foreach($orderArray as $key) {
        if(array_key_exists($key,$array)) {
            $ordered[$key] = $array[$key];
            unset($array[$key]);
        }
    }
    return $ordered + $array;
}

दूसरा सुझाव

$properOrderedArray = array_merge(array_flip(array('name', 'dob', 'address')), $customer);

मैं बताना चाहता था कि ये दोनों सुझाव कमाल के हैं। हालांकि, वे सेब और संतरे हैं। अंतर? एक गैर-सहयोगी मित्रवत है और दूसरा साहचर्य अनुकूल है। यदि आप 2 पूरी तरह से साहचर्य सरणियों का उपयोग कर रहे हैं तो सरणी मर्ज / फ्लिप वास्तव में विलय हो जाएगा और अन्य साहचर्य सरणी को अधिलेखित कर देगा। मेरे मामले में वह परिणाम नहीं है जिसकी मुझे तलाश थी। मैंने अपना क्रम क्रम सरणी बनाने के लिए settings.ini फ़ाइल का उपयोग किया। डेटा सरणी जो मैं छांट रहा था, उसे मेरे सहयोगी सॉर्टिंग समकक्ष द्वारा लिखे जाने की आवश्यकता नहीं थी। इस प्रकार सरणी मर्ज मेरे डेटा सरणी को नष्ट कर देगा। दोनों महान विधियां हैं, दोनों को किसी भी डेवलपर टूलबॉक्स में संग्रहीत करने की आवश्यकता है। अपनी आवश्यकताओं के आधार पर आप पा सकते हैं कि आपको वास्तव में अपने अभिलेखागार में दोनों अवधारणाओं की आवश्यकता है।


1

मैंने इसकी संक्षिप्तता के लिए @ Darkwaltz4 से उत्तर को अपनाया और साझा करना चाहूंगा कि कैसे मैंने उन परिस्थितियों के समाधान को अनुकूलित किया जहां सरणी में प्रत्येक पुनरावृत्ति के लिए अलग-अलग कुंजी हो सकती हैं:

Array[0] ...
['dob'] = '12/08/1986';
['some_key'] = 'some value';

Array[1] ...
['dob'] = '12/08/1986';

Array[2] ...
['dob'] = '12/08/1986';
['some_key'] = 'some other value';

और "मास्टर कुंजी" बनाए रखा जैसे:

$master_key = array( 'dob' => ' ' ,  'some_key' => ' ' );

array_merge ने Array [1] पुनरावृति को $ master_key के आधार पर मर्ज निष्पादित किया होगा और उस पुनरावृत्ति के लिए एक खाली मान ['some_key'] = '' का निर्माण किया था। इसलिए, array_intersect_key का उपयोग प्रत्येक पुनरावृत्तियों में $ master_key को संशोधित करने के लिए किया गया था:

foreach ($customer as $customer) {
  $modified_key = array_intersect_key($master_key, $unordered_array);
  $properOrderedArray = array_merge($modified_key, $customer);
}

0

थोड़ा देर से, लेकिन मैं इसे लागू करने का तरीका नहीं खोज सका, इस संस्करण को बंद करने की आवश्यकता है, php> = 5.3, लेकिन इसे बदल दिया जा सकता है:

$customer['address'] = '123 fake st';
$customer['name'] = 'Tim';
$customer['dob'] = '12/08/1986';
$customer['dontSortMe'] = 'this value doesnt need to be sorted';

$order = array('name', 'dob', 'address');

$keys= array_flip($order);
uksort($customer, function($a, $b)use($keys){
    return $keys[$a] - $keys[$b];
});
print_r($customer);

बेशक 'नॉटसॉर्टम' को क्रमबद्ध करने की आवश्यकता है, और उदाहरण में पहले दिखाई दे सकता है

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