Перестановка массива

#php #arrays #associative-array

#php #массивы #ассоциативный-массив

Вопрос:

Есть ли чистый способ упорядочить этот массив так, чтобы ключ стал идентификатором? Я делал это несколько раз, используя пару foreach и новый массив, куда я помещаю информацию, но я использую около 7 строк кода, и мне было интересно, есть ли что-нибудь чище. Рассматриваемый массив:

 Array ( 
  [0] => Array ( [log_id] => 6  [type] => Test   [other_info] => MoreInfo ) 
  [1] => Array ( [log_id] => 5  [type] => Test2  [other_info] => MoreInfo2 ) 
)
  

Итак, что я хочу получить из приведенного выше массива:

 Array ( 
  [6] => Array ( [type] => Test   [other_info] => MoreInfo ) 
  [5] => Array ( [type] => Test2  [other_info] => MoreInfo2 ) 
)
  

Вы можете видеть, что теперь я ввел идентификатор журнала в качестве ключа. Это занимает у меня несколько строк кода… У вас есть представление о том, как этого можно достичь максимум за 3 или 4 строки?

В качестве альтернативы, есть ли более чистый способ доступа к строке, содержащей * log_id *, который я хочу? Использование, которое я хочу дать этому, заключается в том, что я могу получить доступ к строке определенного * log_id * … В этом случае я бы сделал это с $array[$log_id] помощью … Но если есть решение сделать это без изменения массива (и только с 1 строкой) Я тоже приму это как ответ!

Спасибо!

Комментарии:

1. Есть ли какая-либо причина, по которой вы не можете изначально создать массив с log_id вместо его преобразования?

2. Он поступает из запроса SELECT * FROM … Я не думаю, что смогу, насколько я знаю.

Ответ №1:

Вы не должны беспокоиться о строках кода, которые, элегантный код самодокументируется, что означает, что вы можете прочитать его и понять, что он делает. И он содержит необходимый минимум строк, что обычно занимает больше времени для написания кода.

Противоположность элегантному коду — сжатый, загадочный код, подобный этому, который делает то, что вам нужно для рассматриваемого массива (я вставил его в $data , Demo):

 $data = array_reduce($data, function($v, $w) { $v[array_shift($w)] = $w; return $v;});
  

Это всего лишь одна строка кода, но она не элегантна.

Это можно было бы прочитать намного лучше:

 /**
 * You can leave a comment here.
 * @return array $data keyed with first value of each value
 */
function first_as_key(Array $data)
{
    $keyed = array();
    foreach($data as $v)
        $keyed[array_shift($v)] = $v
        ;
    return $keyed;
}
  

Чаще всего гораздо лучше иметь данные под рукой в форме, которая не требует их транспонирования. Кроме того, если вам нужно выполнить транспонирование, создайте себе функцию, которая сделает эту работу за вас.

Ответ №2:

Но зачем вам нужно несколько операторов foreach? Разве это не ответило бы на ваш вопрос:

 $new_arr = array();
foreach ($old_arr as $row) {
    $new_arr[$row['log_id']][] = $row;
}
  

Единственное отличие заключается в том, что новые строки по-прежнему будут иметь ключ log_id, но я сомневаюсь, что это вас беспокоит. За исключением этого, я нахожу это очень понятным.

Комментарии:

1. да .. вот как я это делаю… но некоторые из них имеют несколько fors, если бы у меня был результат, в котором log_id, например, повторяется, и мне нужно создать другой массив внутри ключа log_id для хранения всех данных с этим log_id.

2. Ах, я понимаю, почему у вас изначально была проблема. Но это легко исправить, и я обновил свой пример, чтобы включить его: я добавил, [] чтобы $new_arr[log_id] всегда был массивом (иногда в нем может быть только один элемент / строка, но, на мой взгляд, это нормально — вы действительно сможете обработатьих унитарно). Дайте мне знать, если это сработает для вас.

3. Кстати, решения с использованием array_map и т. Д. этот вариант использования выглядел бы очень некрасиво (если вообще возможно реализовать).

Ответ №3:

Я не уверен, что есть хороший способ сделать это и не создавать новый массив (поскольку, если вы просто работаете с существующим массивом, у вас могут возникнуть коллизии ключей (в вашем примере, что произойдет, если первый элемент будет иметь log_id 1?)

Это можно поместить в одну строку, используя create_function функцию php, но это довольно плохо для удобства чтения. Все, что у вас есть, используя 6 или 7 строк, вероятно, лучший способ сделать это.

Но ради аргумента, вот один из способов сделать это в 2 строки, используя array_walk:

 <?php 
$test = array();
$test[] = array('id' => 6, 'data' => 'asdf');
$test[] = array('id' => 7, 'data' => 'qwer');

print_r($test);

$result = array();
array_walk($test, create_function('amp;$val,$key', 'global $resu< $result[$val['id']] = $val;'));
print_r($result);
?>
  

Из любопытства, как вы создаете массив? Если он поступает из какой-либо базы данных, вероятно, лучше создать ключ при добавлении записи.