2008-12-08 42 views
109

Có thể trong PHP để làm một cái gì đó như thế này? Làm thế nào bạn sẽ đi về viết một chức năng? Đây là một ví dụ. Thứ tự là thứ quan trọng nhất.Sắp xếp một mảng bằng các phím dựa trên một mảng khác?

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

Và tôi muốn làm một cái gì đó giống như

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

Bởi vì cuối cùng tôi sử dụng một foreach() và họ không theo thứ tự đúng (vì tôi gắn giá trị cho một chuỗi cần phải theo thứ tự đúng và tôi không biết trước tất cả các khóa/giá trị mảng).

Tôi đã xem xét các hàm mảng nội bộ của PHP nhưng có vẻ như bạn chỉ có thể sắp xếp theo thứ tự bảng chữ cái hoặc số.

Trả lời

267

Chỉ cần sử dụng array_merge hoặc array_replace. Array_merge công trình bằng cách bắt đầu với mảng bạn cho nó (theo thứ tự thích hợp) và ghi đè/thêm các phím với dữ liệu từ mảng thực tế của bạn:

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

ps - tôi trả lời câu hỏi này 'cũ', bởi vì tôi nghĩ rằng tất cả các vòng được đưa ra như câu trả lời trước là quá mức cần thiết.

+22

Nó hoạt động độc đáo nếu bạn có các phím chuỗi nhưng không phải cho số. Tài liệu PHP: "Nếu các mảng đầu vào có cùng các khóa chuỗi, thì giá trị sau đó cho khóa đó sẽ ghi đè lên khóa trước đó. Tuy nhiên, các mảng có chứa các phím số, giá trị sau sẽ không ghi đè giá trị ban đầu, nhưng sẽ được thêm vào. " – bolbol

+3

Rất tốt, nhưng điều gì sẽ xảy ra nếu các khóa không tồn tại trong các giá trị? Tôi cần điều này, nhưng chỉ khi có bất kỳ chìa khóa nào tồn tại ... Có lẽ cần phải tìm kiếm nó ... –

+4

cho trường hợp của tôi là array_replace thay vì array_merge. array_merge kết hợp cả hai giá trị thay vì thay thế mảng thứ hai thành các khóa được sắp xếp. – neofreko

89

Có bạn đi:

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; 
} 
+11

Vì vậy, bạn có thể tham gia 2 mảng bằng dấu +? Tôi không bao giờ biết điều đó, tôi đã sử dụng 'array_merge()'! – alex

+3

Điều này có tốt hơn việc sử dụng 'usort()' hay 'uasort()'? – grantwparks

+2

'foreach ($ orderArray là $ key => $ v)' đã thực hiện thủ thuật cho tôi –

21
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; 
} 
2

NẾU bạn có mảng trong mảng của bạn, bạn sẽ phải thích ứng với chức năng của Eran một chút ...

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

Đưa một mảng làm đơn đặt hàng của bạn:

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

Y ou có thể sắp xếp một mảng dựa trên giá trị sử dụng array_intersect­Docs:

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

Hoặc trong trường hợp của bạn, để sắp xếp theo phím, sử dụng array_intersect_key­Docs:

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

Cả hai chức năng sẽ giữ thứ tự của các tham số đầu tiên và sẽ chỉ trả về các giá trị (hoặc các khóa) từ mảng thứ hai.

Vì vậy, đối với hai trường hợp tiêu chuẩn này, bạn không cần tự viết một hàm để thực hiện sắp xếp/sắp xếp lại.

+0

Giao lộ sẽ loại bỏ những mục mà anh ta không biết trước. – DanMan

+1

Điều này không chính xác khi sắp xếp theo các phím. array_intersect_key sẽ chỉ trả về các giá trị từ array1, không phải array2 – pavsid

+0

Đồng ý với pavsid - ví dụ array_intersect_key là không chính xác - nó trả về các giá trị từ mảng đầu tiên, không phải là giá trị thứ hai. –

0

Đầu tiên Đề xuất

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

Second Đề xuất

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

tôi muốn chỉ ra rằng cả hai lời đề nghị rất tuyệt vời. Tuy nhiên, chúng là táo và cam. Sự khác biệt? Một là không thân thiện kết hợp và một là thân thiện kết hợp. Nếu bạn đang sử dụng 2 mảng kết hợp hoàn toàn thì mảng phối/lật sẽ thực sự hợp nhất và ghi đè lên mảng kết hợp khác. Trong trường hợp của tôi đó không phải là kết quả tôi đang tìm kiếm. Tôi đã sử dụng tệp settings.ini để tạo mảng sắp xếp thứ tự của mình. Mảng dữ liệu tôi sắp xếp không cần phải được viết bởi đối tác sắp xếp liên kết của tôi. Vì vậy mảng hợp nhất sẽ phá hủy mảng dữ liệu của tôi.Cả hai đều là phương pháp tuyệt vời, cả hai đều cần được lưu trữ trong bất kỳ hộp công cụ dành cho nhà phát triển nào. Dựa trên nhu cầu của bạn, bạn có thể thấy bạn thực sự cần cả hai khái niệm trong kho lưu trữ của bạn.

0

Tôi chấp nhận câu trả lời từ @ Darkwaltz4 cho ngắn gọn của nó và muốn chia sẻ làm thế nào tôi thích giải pháp cho tình huống mà các mảng có thể chứa các phím khác nhau cho mỗi lần lặp như vậy:

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

và duy trì một " chìa khóa vạn" như vậy:

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

array_merge sẽ thực hiện việc hợp nhất trong Array [1] lặp dựa trên $ master_key và sản xuất [ 'some_key'] = '', một giá trị rỗng, cho lặp đó. Do đó, array_intersect_key được sử dụng để sửa đổi $ master_key trong mỗi lần lặp như vậy:

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

Một cách khác cho 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); 

Kết quả:

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

trình tốt với chuỗi và các phím số.

+1

+ Trong khi cả hai đều làm việc, tôi tìm thấy 'array_replace()' để chuyển tiếp ý định tốt hơn 'array_merge()'. –

+0

'array_replace' cũng để nguyên loại biến còn nguyên vẹn. Nếu một trong các giá trị trong mảng của bạn sẽ là '(string) '1'' và bạn đã sử dụng toán tử' + ', giá trị sẽ được chuyển thành' (int) 1' –

+0

. các phím ('array_merge()' sẽ chỉ thêm chúng?). Logic được giải thích rất rõ [ở đây] (https://www.designcise.com/web/tutorial/how-to-sort-an-array-by-keys-based-on-order-in-a-secondary- array-in-php). * Đầu tiên *, 'array_flip()' thay đổi giá trị của mảng $ order thành các khóa. * Thứ hai *, 'array_replace()' thay thế các giá trị của mảng đầu tiên bằng các giá trị có cùng các khóa trong mảng thứ hai. Nếu bạn cần sắp xếp một mảng theo các phím từ khóa khác, bạn thậm chí không phải sử dụng 'mảng_flip'. –

0

PHP có chức năng để giúp bạn với điều này:

$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 làm tất cả công việc cho bạn và array_search cung cấp các phím. array_search() trả về false khi nó không thể tìm thấy một kết quả phù hợp vì vậy các mục không nằm trong mảng sắp xếp sẽ tự động di chuyển đến đáy của mảng.

Lưu ý: uasort() sẽ sắp xếp mảng mà không ảnh hưởng đến các mối quan hệ khóa => giá trị.

23

Làm thế nào về giải pháp này

$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

Một hơi muộn, nhưng tôi không thể tìm ra cách tôi thực hiện điều đó, phiên bản này cần đóng cửa, php> = 5.3, nhưng có thể được thay đổi không:

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

Dĩ nhiên 'dontSortMe' cần phải được sắp xếp ra ngoài, và có thể xuất hiện đầu tiên trong ví dụ

0
  • loại theo yêu cầu
  • tiết kiệm cho int- các phím (vì mảng_replace)
  • không trả về các khóa không tồn tại trong inputArray
  • (tùy chọn) các phím lọc không có trong danh sách khóa đã cho

Code:

/** 
* 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

Chức năng này trả về một phụ và mảng được sắp xếp dựa vào tham số thứ hai $ phím

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

Ví dụ:

$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

tôi đã sử dụng giải pháp của Darkwaltz4 nhưng sử dụng array_fill_keys thay vì array_flip, để điền vào NULL nếu khóa không được đặt trong $array.

$properOrderedArray = array_replace(array_fill_keys($keys, null), $array); 
Các vấn đề liên quan