2011-12-22 40 views
13

tôi có các mảng sau:Sắp xếp mảng bởi hai thuộc tính đối tượng sử dụng chức năng ẩn danh

Array 
(
    [0] => stdClass Object 
     (
      [timestamp] => 1 
      [id] => 10 
     ) 

    [1] => stdClass Object 
     (
      [timestamp] => 123 
      [id] => 1 
     ) 

    [2] => stdClass Object 
     (
      [timestamp] => 123 
      [id] => 2 
     ) 

) 

Tôi hiện đang sử dụng đoạn mã sau để sắp xếp mảng bằng tài sản timestamp:

function sort_comments_by_timestamp(&$comments, $prop) 
{ 
    usort($comments, function($a, $b) use ($prop) { 
     return $a->$prop < $b->$prop ? 1 : -1; 
    }); 
} 

thế nào tôi cũng có thể sắp xếp id theo số id giảm dần khi dấu thời gian giống nhau không?

+1

Có lý do nào khiến bạn gọi nó là '_by_timestamp', nhưng cũng có tham số' $ prop'? – Matthew

+1

@Matthew khác với 'Tôi đã làm một số thử nghiệm' và đặt tên xấu? Không :) Đã sửa nó btw – PeeHaa

Trả lời

17

Đề xuất là gửi trong một mảng với $ props

function sort_comments_by_timestamp(&$comments, $props) 
{ 
    usort($comments, function($a, $b) use ($props) { 
     if($a->$props[0] == $b->$props[0]) 
      return $a->$props[1] < $b->$props[1] ? 1 : -1; 
     return $a->$props[0] < $b->$props[0] ? 1 : -1; 
    }); 
} 

Và sau đó gọi nó với

sort_comments_by_timestamp($unsorted_array,array("timestamp","id")); 

Nếu bạn muốn nó để làm việc với X số $ đạo cụ bạn có thể làm một vòng lặp bên trong usort luôn so sánh thuộc tính với thuộc tính trước của nó trong mảng như sau:

function sort_comments_by_timestamp(&$comments, $props) 
{ 
    usort($comments, function($a, $b) use ($props) { 
     for($i = 1; $i < count($props); $i++) { 
      if($a->$props[$i-1] == $b->$props[$i-1]) 
       return $a->$props[$i] < $b->$props[$i] ? 1 : -1; 
     } 
     return $a->$props[0] < $b->$props[0] ? 1 : -1; 
    }); 
} 

Chúc mừng!

+1

Nếu bạn gặp lỗi: 'Mảng để chuyển đổi chuỗi' bạn cần phải thay thế tất cả' $ a -> $ props [X] 'thành' $ a -> {$ props [X]} ' –

2
$result = -1; 
if ($a->timestamp < $b->timestamp) { 
    $result = 1; 
} else if ($a->timestamp === $b->timestamp) { 
    if ($a->id < $b->id) $result = 1; 
} 
return $result; 

Đặt điều này trong quá trình đóng gói usort. Bạn cũng có thể loại bỏ đối số $ prop và phần use ($prop).

3
function sort_comments_by_timestamp(&$comments, $prop) 
{ 
    usort($comments, function($a, $b) use ($prop) { 
     if ($a->$prop == $b->$prop) 
      return $b->id - $a->id; 
     else 
      return $a->$prop < $b->$prop ? 1 : -1; 
    }); 
} 

Thông số $prop trước và sau đó là số phụ id.

0

sắp xếp theo số lượng tiêu chí tùy ý. Tôi luôn luôn quên nếu $ a - $ b sắp xếp tăng dần hoặc giảm dần. Điều chỉnh khi cần.

$comparatorSequence = array(
    function($a, $b) { 
     return $a->timestamp - $b->timestamp; 
    } 
    , function($a, $b) { 
     return $a->id - $b->id; 
    } 
); 

usort($theArray, function($a, $b) use ($comparatorSequence) { 
    foreach ($comparatorSequence as $cmpFn) { 
     $diff = call_user_func($cmpFn, $a, $b); 
     if ($diff !== 0) { 
      return $diff; 
     } 
    } 
    return 0; 
}); 
4

Bạn có thể làm điều đó với ouzo goodies (Tôi biết bạn đã nghe về điều này: P).

$result = Arrays::sort($array, 
    Comparator::compound(
     Comparator::compareBy('timestamp'), 
     Comparator::compareBy('id') 
    ) 
); 
2

Tôi biết điều này là khá câu hỏi cũ tuy nhiên không tìm thấy nhiều thông tin cho khi bạn muốn sắp xếp theo nhiều thuộc tính kinda như mySQL ORDERBY không vì vậy đây là một chức năng từ một khuôn khổ cá nhân

Tùy chọn 1: trật tự ($ key, $ hướng = 'asc'), nơi $ key là một tài sản của các đối tượng và $ hướng là 'asc' hoặc 'desc'

Phương án 2: trật tự (mảng ($ key => $ direction, $ key => $ direction)) Điều này tương tự như tùy chọn 1 tuy nhiên khi 2 đối tượng có cùng giá trị cho $ key, tùy chọn sắp xếp thứ hai từ mảng được truyền được sử dụng.

public function order($arr, $key=null, $direction='ASC'){ 
    if(!is_string($key) && !is_array($key)) 
     throw new InvalidArgumentException("order() expects the first parameter to be a valid key or array"); 

    $props = array(); 

    if(is_string($key)) { 
     $props[$key] = strtolower($direction) == 'asc' ? 1 : -1; 
    }else{ 
     $i = count($key); 
     foreach($key as $k => $dir){ 
      $props[$k] = strtolower($dir) == 'asc' ? $i : -($i); 
      $i--; 
     } 
    } 

    usort($arr, function($a, $b) use ($props){ 
     foreach($props as $key => $val){ 
      if($a->$key == $b->$key) continue; 
      return $a->$key > $b->$key ? $val : -($val); 
     } 
     return 0; 
    }); 

    return $arr; 

} 
+0

Nice, cảm ơn bạn. – shanebp

+0

Rất nhiều chào mừng :) –

+0

Chức năng nhỏ rất đẹp. Tôi đã sử dụng câu trả lời được chấp nhận cho nhu cầu phân loại của mình (với một số chỉnh sửa cá nhân) và quyết định ngừng hoạt động sau khi cập nhật CMS của trang web.Điều này đã cứu tôi một loạt thời gian cố gắng để gỡ lỗi những gì vấn đề là/được. –

Các vấn đề liên quan