Truy cập một mảng kết hợp theo chỉ mục số nguyên trong PHP


92

Tôi muốn đặt giá trị của một mảng kết hợp bằng cách sử dụng chỉ số mảng của cặp khóa / giá trị. Ví dụ:

$my_arr = array( "bling" => "some bling", "bling2" => "lots O bling" );
$my_arr[1] = "not so much bling";  // Would change the value with key bling2.

Làm cách nào để có thể thực hiện được điều này mà không cần sử dụng chuỗi khóa?

Câu trả lời:


188

Sử dụng array_keys .

$keys = array_keys($my_arr);
$my_arr[$keys[1]] = "not so much bling";

Hi vọng điêu nay co ich.


4
Lưu ý thêm, tại sao các nhà phát triển PHP lại tạo ra một cách truy cập vào một mảng không trực quan như vậy?
Marty

3
@Marty điều này ít liên quan đến cách các nhà phát triển PHP triển khai nó, nhưng nhiều hơn do bạn hiểu sai về cách hoạt động của mảng. Về mặt kỹ thuật, ở trên vẫn sử dụng tên liên kết. Không có mối tương quan giữa các khóa chỉ mục số và chỉ mục kết hợp.
Gordon

2
Bạn tạo một mảng kết hợp bởi vì những gì bạn đang tìm kiếm quan trọng hơn vị trí của nó trong mảng. Tôi nghĩ đây là một điểm tốt. Giả sử bạn có một mảng với tên sinh viên là khóa và địa chỉ là giá trị. Bạn có thể liên hệ với địa chỉ của sinh viên bằng tên của nó. Vị trí của mảng nó không liên quan. Và bạn có thể sắp xếp mảng theo name of the student.
Donovan

@Gordon về mặt kỹ thuật thì đó là sự thật. Nhưng lập trình viên đang cung cấp một số, không phải một chuỗi. Tôi nghĩ rằng đây là ý nghĩa của without using a key string.
Donovan

2
@Albert bạn đang ánh xạ số này với chuỗi khóa thích hợp. Điều đó không có nghĩa là array[1] === $array['foo']mặc dù. Mảng vẫn có thể chứa một giá trị khác tại $array[1]. Lưu ý rằng tôi không nói rằng giải pháp của bạn là sai. Đó là giả định của OP.
Gordon

27

Không có mối tương quan giữa các khóa chỉ mục số và chỉ mục kết hợp.

Khi bạn nói rằng bạn muốn đặt giá trị của một mảng kết hợp bằng cách sử dụng chỉ số mảng của khóa / giá trị , thì bạn phải sử dụng khóa đã cho, cài đặt $array[1]không giống như cài đặt $array['foo'].

Hãy xem xét mảng này

print_r( array('foo', 'foo' => 'bar', 'baz', 'some' => 'value') );

Điều này sẽ cho

Array
(
    [0] => foo
    [foo] => bar
    [1] => baz
    [some] => value
)

Foo là phần tử thứ hai trong mảng. Đó là phần , nhưng nó không liên quan gì đến chỉ số 1. Như bạn có thể thấy, trong mảng ở trên, chỉ số 1 được liên kết với baz. Sai lầm khi cho rằng chỉ vì foolà khóa kết hợp đầu tiên nên nó có liên quan gì đến khóa số thực 1. Giống như somekhông tương quan với 2.

Tương tự như vậy, đối với một mảng hỗn hợp như được hiển thị ở trên, giải pháp được array_keysđề xuất ở nơi khác trên trang web này sẽ không hoạt động, bởi vì

print_r( array_keys(array('foo', 'foo' => 'bar', 'baz', 'some' => 'value')) );

sẽ cho

Array
(
    [0] => 0
    [1] => foo
    [2] => 1
    [3] => some
)

Vì vậy, khi bạn làm $array[$keys[1]]bạn đang thực sự làm $array['foo']. Nhưng nếu bạn muốn truy cập giá trị kết hợp thứ hai trong mảng ( 'some') đó, bạn không thể làm $array[$keys[2]]vì điều đó sẽ đánh giá đến $array[1]và đó là baz.

Phần bù đắp của một phần tử hoàn toàn không liên quan đến khóa hoặc giá trị của nó

print_r(
    array(
        100    => 'foo',
        'foo'  => 'bar',
        50     => 'baz',
        'some' => 'value'
    )
);

Thực sự có nghĩa là

Array
( //key       value     offset/position
    [100]  => foo       // 0
    [foo]  => bar       // 1
    [50]   => baz       // 2
    [some] => value     // 3
)

có nghĩa là phần tử ở độ lệch 0 là foo mặc dù khóa của nó là 100. Nếu bạn muốn trích xuất các phần tử từ một mảng bằng phần bù, bạn phải sử dụng

$third = array_splice($array, 2, 1);
echo $third[0]; // baz

Điều này sẽ tạo ra một mảng chỉ chứa phần tử ở vị trí thứ ba.

Hoặc bạn có thể sử dụng một ArrayIterator. Các ArrayIteratordụng cụ một Seekablegiao diện cho phép bạn tìm đến một vị trí cụ thể / bù đắp trong mảng và sau đó lấy rằng:

$iterator = new ArrayIterator($array);
$iterator->seek(3);
echo $iterator->current(); // value

Vấn đề nhỏ: "nếu bạn muốn truy cập giá trị liên kết thứ hai trong mảng đó ('some'), bạn không thể thực hiện $ array [$ key [2]] bởi vì điều đó sẽ đánh giá thành $ array [1] và đó là baz" Về mặt kỹ thuật, đó là bởi vì tất cả các khóa, kể cả các khóa số, đều là khóa liên kết - 4 giá trị được trả về array_keys. Không có thực thể nào như "khóa không liên kết". Nếu bạn muốn chỉ ra rằng bạn không thể trả lại khóa chuỗi thứ 2 (bằng cách giả sử mảng khóa chỉ chứa chuỗi), thì điều bạn nói là đúng. $stringKeys = array_filter(array_keys($array), "is_string");cung cấp cho các khóa chuỗi.
ToolmakerSteve

17

Trong khi array_keys()cho phép truy cập vào khóa thứ n, array_valuessẽ cung cấp cho bạn giá trị thứ n.

<?php
$array = [
   0     => 'Zero',
   '1'   => 'One',
   'Two' => 'Two',
];
echo array_values($array)[2];
?>

sẽ xuất ra 'Hai'.

Có lợi thế của cái này hơn cái kia không? Chà, điểm nhỏ duy nhất tôi có thể thấy là số lượng truy cập mảng.

Với array_keys()bạn cần đến 3.

  1. Lấy các khóa từ mảng dữ liệu.
  2. Nhận khóa thứ n từ danh sách các khóa.
  3. Nhận giá trị bằng cách sử dụng khóa thứ n từ mảng dữ liệu.

Với array_values(), bạn chỉ cần 2.

  1. Nhận các giá trị từ mảng dữ liệu.
  2. Nhận giá trị thứ n từ danh sách các giá trị.

Tuy nhiên, mặt khác, các khóa thường nhỏ hơn và dữ liệu có thể được lồng vào nhau rất lớn, vì vậy, về mặt cân bằng, sử dụng khóa array_keys()có lẽ an toàn hơn.


3

Nếu mảng lớn, cả hai array_keysarray_valuessẽ lãng phí vì chúng sẽ phân bổ một mảng mới có cùng kích thước với mảng ban đầu, chỉ để lấy khóa (hoặc giá trị) thứ n .

array_slicechấp nhận một phần bù số nguyên và hoạt động trên các mảng kết hợp. Bạn có thể sử dụng nó để lấy (và đặt) khóa thứ n trong thời gian không đổi.

// This will at most allocate 2 temporary arrays of 1 element each
$key = array_keys(array_slice($array, $n, 1, true))[0];

$array[$key] = $value;

2
Giải pháp tốt ở đây!
Daan

1

Thử cái này. Nó hoạt động cho bạn.

$result= array_values($my_arr); // Array with indexes you need

1
Hãy cẩn thận khi đăng lên một chủ đề cũ đã có một số phản hồi và một câu trả lời được chấp nhận. Bạn cần giải thích tại sao câu trả lời mới của bạn tốt hơn câu trả lời hiện có.
APC

0

Một khả năng khác là chuyển đổi nó thành một mảng bình thường:

$ arraybuff = implode ("~~~", $ my_arr);
$ my_arr = boom ("~~~", $ arraybuff);

Trong đó "~~~" là dấu phân cách sẽ không xuất hiện trong dữ liệu của bạn.

Bây giờ bạn có thể truy cập mảng bằng cách sử dụng các chỉ số số bằng các hiệu số.

Nếu bạn vẫn cần giữ lại mảng kết hợp của mình, chỉ cần gán nó cho một biến khác.


Vì bạn nên luôn luôn và luôn xem xét, dấu phân cách chính xác này có thể xuất hiện trong dữ liệu của bạn, ý tưởng này chỉ hoạt động trong 99,9999999%. Có một số giải pháp sẽ hoạt động 100%. Bên cạnh đó, điều này khiến bộ xử lý hoạt động rất nhiều và lãng phí bộ nhớ chỉ cho một truy cập mảng đơn giản.
user426486
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.