2015-06-16 13 views
5

Tôi thực sự thích kiểu lập trình hàm sử dụng bản đồ mảng để tạo một mảng các đối tượng từ một mảng đối tượng khác.Tôi có thể đặt các khóa của mảng bằng cách sử dụng các hàm mảng như array_map

$newObjects = array_map(
    function($oldObject) { 
    return new NewObject($oldObject); 
    }, 
    $oldObjects 
); 

Mà tất cả hoạt động tốt nhưng tôi thực sự muốn để có thể thiết lập các chỉ số của mảng để họ có id của các đối tượng ban đầu cho việc tìm kiếm dễ dàng hơn và hồi từ mảng nhưng tôi không thể nghĩ ra cách làm điều khác thì không thanh lịch.

$newObjects = array(); 
foreach ($oldObjects as $oldObject) { 
    $newObjects[$oldObject->getId()] = new NewObject($oldObject); 
} 

Có cách nào tôi có thể thực hiện việc này không?

+0

Nhận xét ủng hộ của Devil: nhiều như tôi thích bản đồ/giảm/đi bộ, vv đôi khi một 'foreach' là giải pháp đơn giản nhất, dễ đọc :) –

+0

Có, tôi đồng ý, ngựa cho các khóa học và tất cả. Nhìn vào gợi ý bên dưới foreach có nhiều thứ hơn cho nó về phong cách và khả năng đọc –

Trả lời

1

Điều gì sẽ xảy ra nếu bạn sử dụng array_walk và một mảng tạm thời với các chỉ mục mới của mình.

$array = ['A', 'B', 'C', 'D']; 
    $reIndexedTemp = []; 

    array_walk(
     $array, 
     function ($item, $key) use (&$reIndexedTemp) { 
      // here you can have your logic to assemble your new index 
      $reIndexedTemp[$key + 100] = $item; 
     } 
    ); 

    //$array = $reIndexedTemp; 

    var_dump($array, $reIndexedTemp); 

đầu ra (không có dòng nhận xét):

array(4) { 
    [0] => 
    string(1) "A" 
    [1] => 
    string(1) "B" 
    [2] => 
    string(1) "C" 
    [3] => 
    string(1) "D" 
} 
array(4) { 
    [100] => 
    string(1) "A" 
    [101] => 
    string(1) "B" 
    [102] => 
    string(1) "C" 
    [103] => 
    string(1) "D" 
} 
+0

Hmm, tôi nghĩ rằng đó là ít thanh lịch! Tôi không muốn sử dụng một mảng tạm thời. Ngoài ra, $ key chỉ là khóa ban đầu không liên quan đến sự trung thực. –

+0

Im không phải là một fan hâm mộ của mảng temp :), nhưng tất cả những chức năng mảng mà tôi có thể nghĩ đến là chuyển tiếp trên các chỉ số mảng vì lý do rõ ràng. Và thao tác một phần giữa của một quá trình xử lý mảng chính nó không có vẻ là một ý tưởng tốt. nếu bạn không cần khóa từ mảng ban đầu thì bạn có thể bỏ qua phương thức array_walk và giữ mảng array_map nhưng tôi sợ mảng tạm thời vẫn sẽ được yêu cầu! – Ali

+1

Nó không phải là một mảng tạm thời. Nó lưu trữ đầu ra bạn cần. Thật không may 'array_walk()' sửa đổi mảng mà nó nhận được làm đối số và không trả về bất kỳ giá trị hữu ích nào.Nó không thể được sử dụng trực tiếp theo kiểu lập trình hàm :-(Nếu bạn cần sử dụng luồng xử lý này ở một số nơi, hãy nghĩ đến việc đóng gói mã ở trên trong một hàm trả về mảng "tạm thời" (và thực hiện mong muốn của bạn cho kiểu lập trình hàm).) – axiac

0

Nhìn xung quanh - Looking for array_map equivalent to work on keys in associative arrays

gợi ý nó có thể làm việc sử dụng array_combine

Vì vậy, tôi đoán nó sẽ là

$newObjects = array_combine(
    array_map(
    function($oldObject) { 
     return $oldObject->getId(); 
    }, 
    $oldObjects 
), 
    array_map(
    function($oldObject) { 
     return new NewObject($oldObject); 
    }, 
    $oldObjects 
) 
); 

Hmm có lẽ là tốt nhất, chỉ phía bên này của bị thổi phồng nhưng chắc chắn hơn rất nhiều phức tạp hơn so với foreach

+0

Snap! Sắp xếp ... Tôi chỉ nhìn thấy bài đăng của bạn sau khi tôi gửi bài đăng của tôi –

1

Tôi nghĩ rằng một foreach có lẽ là giải pháp có thể đọc được hầu hết trong trường hợp này, nhưng bạn có thể sử dụng array_map() với array_combine() để đạt được những gì bạn muốn. Một cái gì đó như:

// empty array to store the old object ids 
$ids = []; 

// map over old objects, inheriting $id 
// from parent scope by reference 
$objs = array_map(function($oldObject) use (&$ids) { 
    $ids[] = $oldObject->getId(); 
    return new NewObject($oldObject); 
}, $oldObjects); 

// combine id and object arrays 
$newObjects = array_combine($ids, $objs); 

Hope this helps :)

+0

Ah vâng, đó là một chút neater so với tôi Mặc dù vì một lý do tôi không thích mảng bên ngoài (tôi có một không thích hợp các đối tượng được truyền đi bằng tham chiếu!) –

+0

Haha, đủ công bằng! Có vẻ hơi gnarly alright.Thêm ngôn ngữ 'chức năng' làm điều tương tự hơn một cách minh bạch. PHP không phải là ngôn ngữ đẹp nhất mà tôi đoán, nhưng chúng tôi vẫn yêu nó ... phải không? –

2

Đó là - array_reduce() là chính xác những gì bạn cần:

class Bar 
{ 
     protected $id; 

     public function __construct($id) 
     { 
       $this->id = $id; 
     } 

     public function getId() 
     { 
       return $this->id; 
     } 
} 

class Foo 
{ 
     protected $bar; 

     public function __construct(Bar $bar) 
     { 
       $this->bar = $bar; 
     } 
} 

$oldObjects = [new Bar('x'), new Bar('y'), new Bar('z')]; 

$newObjects = array_reduce($oldObjects, function($current, Bar $obj) { 
     $current[$obj->getId()] = new Foo($obj); 
     return $current; 
}, []); 

này sẽ làm tất cả tại chỗ mà không cần phải dành nhiều bộ nhớ trên thêm các mảng giống như cho array_combine()

Tuy nhiên, tôi khuyên bạn nên sử dụng các cấu trúc như vậy khi cần thiết. Sử dụng điều này chỉ vì nó "có vẻ tốt hơn" có thể không phải là một ý tưởng tốt - vì các vòng lặp đơn giản trong hầu hết các trường hợp chỉ dễ đọc hơn.

+0

Hmm, thú vị.Để tìm hiểu thêm một chút về điều đó để có được cách hoạt động đúng cách (không bao giờ thực sự được sử dụng array_reduce nhiều) Tôi đồng ý ry nhiều về điều này không nhất thiết phải là cách tiếp cận tốt nhất và cân bằng Tôi nghĩ rằng hoặc foreach hoặc các tùy chọn array_combine cung cấp sự cân bằng tốt nhất hoặc dễ đọc và sang trọng. Đây là một bài tập hiểu biết hơn là đòi hỏi phải tìm cách tiếp cận chức năng tốt hơn cách tiếp cận chức năng (mặc dù nó sẽ tốt) –

+0

Ở dưới cùng, tất cả các tùy chọn này sẽ được chuyển xuống vòng lặp. chỉ để che giấu nó dưới mui xe –

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