Подтвердить что ты не робот

PHP-массив копирует определенные ключи, встроенные функции? Производительность вложенного контура?

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

Вот мои массивы:

$data[123] = 'aaa';
$data[423] = 'bbb';
$data[543] = 'ccc';
$data[231] = 'ddd';
$data[642] = 'eee';
$data[643] = 'fff';
$data[712] = 'ggg';
$data[777] = 'hhh';

$keys_to_copy[] = '123';
$keys_to_copy[] = '231';
$keys_to_copy[] = '643';
$keys_to_copy[] = '712';
$keys_to_copy[] = '777';

$copied_data[123] = 'aaa';
$copied_data[231] = 'ddd';
$copied_data[643] = 'fff';
$copied_data[712] = 'ggg';
$copied_data[777] = 'hhh';

Я мог бы просто пропустить массив данных следующим образом:

foreach ($data as $key => $value) {
  if ( in_array($key, $keys_to_copy)) {
    $copied_data[$key] = $value;
  }
}

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

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

Но я хотел бы знать, есть ли способ сделать это со встроенными функциями PHP.
Я посмотрел на array_intesect_key(), но это не совсем так, потому что у моего массива $keys_to_copy есть мои нужные ключи как значения массива, а не ключи.

У кого-нибудь есть идеи?

Приветствия, B

4b9b3361

Ответ 1

Я справился с этим - у меня почти было это выше. Я думал, что все равно отправлю ответ за полноту. Надеюсь, это поможет кому-то!

array_intersect_key($data, array_flip($keys_to_copy))

Используйте array_flip() для переключения $keys_to_copy, чтобы его можно было использовать в array_intersect_keys()

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

EDIT:
Я проверил некоторые тесты, используя PHP CLI, чтобы сравнить код foreach() в моем вопросе с кодом в моем ответе выше. Результаты довольно поразительны. Вот код, который я использовал для сравнения, который, на мой взгляд, действителен:

<?php
ini_set('max_execution_time', 0);//NOT NEEDED FOR CLI

// BUILD RANDOM DATA ARRAY
$data = array();
while ( count($data) <= 200000) {
    $data[rand(0, 500000)] = rand(0, 500000);
}
$keys_to_copy = array_rand($data, 100000);

// FOREACH
$timer_start = microtime(TRUE);
foreach ($data as $key => $value) {
    if ( in_array($key, $keys_to_copy)) {
        $copied_data[$key] = $value;
    }
}
echo 'foreach: '.(microtime(TRUE) - $timer_start)."s\r\n";

// BUILT-IN ARRAY FUNCTIONS
$timer_start = microtime(TRUE);
$copied_data = array_intersect_key($data, array_flip($keys_to_copy));
echo 'built-in: '.(microtime(TRUE) - $timer_start)."s\r\n";
?>

И результаты...
foreach: 662.217s
array_intersect_key: 0.099s

Таким образом, намного быстрее загружает элементы массива для использования функций массива PHP, а не foreach. Я думал, что это будет быстрее, но не так!

Ответ 2

Почему бы не загрузить весь массив результатов в массив, а затем начать обработку с вложенными циклами?

$query_result = mysql_query($my_query) or die(mysql_error());
$query_rows = mysql_num_rows($query_result);
for ($i = 0; $i < $query_rows; $i++)
{
    $row = mysql_fetch_assoc($query_result);
    // 'key' is the name of the column containing the data key (123)
    // 'value' is the name of the column containing the value (aaa)
    $data[$row['key']] = $row['value']; 
}
foreach ($data as $key => $value)
{
    if ( in_array($key, $keys_to_copy)) 
    {
        $copied_data[$key] = $value;
    }
}