Как преобразовать этот массив?

Вот данные

$array = array( 'random' => 1, 'pewpew' => 2, 'temp' => 5, 'xoxo' => 3, 'qweqweqe' => 4, ); $fields = array('random', 'xoxo', 'temp'); 

Мне нужно получить результат:

 $result = array( 'random' => 1, 'xoxo' => 3, 'temp' => 5, ); 

Я имею в виду, что наличие / порядок ключей из $ полей применяется к массиву $.

Возникает вопрос: могу ли я выполнить это преобразование, используя только функции array_? (Я не хочу использовать iteations) Если да: вы можете связать мне функцию, которая мне нужна?

(извините за орфографические ошибки)

UPD.

PHP 5.2

Related of "Как преобразовать этот массив?"

Этот код сохраняет порядок и работает в PHP 5.2 по мере необходимости

Одна линия:

 $result = array_merge( array_flip($fields), array_intersect_key( $array, array_flip( $fields ) ) ); 

Для производительности:

 $flip = array_flip($fields); $result = array_merge( $flip array_intersect_key( $array, $flip ) ); 
 $result=array_intersect_key($array ,array_flip($fields) ); 
 // little trick required here... $fields = array('random' => 0, 'xoxo' => 0, 'temp' => 0); $result = array_intersect_key($array,$fields); 

Меня всегда интересуют эти типы вопросов, где речь идет об эффективном коде (как в использовании кода, так и в скорости). Тем не менее, я пробовал и сравнивал несколько разных методов, и ничто не было столь же эффективным и простым foreach !

Я пробовал все размещенные решения и свой собственный массив_валют и базовый foreach. Я провел несколько тестов, как с массивами, так и с полями, размещенными Miraage, а некоторые с гораздо большими массивами. Я также заметил что-то странное с результатами, например, дополнительные значения, если $ fields имели значения не в $ array.

Я заказал его по скорости.

FOREACH: 0,01245 с

 $result = array(); foreach ($fields as $k) { if (isset($array[$k])) $result[$k] = $array[$k]; } 

ARRAY_DIFF_KEY: 0.01471 с (неожиданные результаты: дополнительные значения)

 $result = array_diff_key($fields, $array); 

FOREACH (функция): 0,02449 с

 function array_filter_by_key($array, $fields) { $result = array(); foreach ($fields as $k) { if (isset($array[$k])) $result[$k] = $array[$k]; } return $result; } 

ARRAY_WALK (по ссылке): 0.09123 сек.

 function array_walk_filter_by_key($item, $key, $vars) { if (isset($vars[1][$item])) $vars[0][$item] = $vars[1][$item]; } $result = array(); array_walk($fields, 'array_walk_filter_by_key', array(&$result, &$array)); 

СПИСОК / КАЖДЫЙ: 0.12456 сек.

 $result = array(); reset($fields); while (list($key, $value) = each($fields)) { if (isset($array[$value])) $result[$value] = $array[$value]; } 

ARRAY_INTERSECT_KEY: 0.27264 sec (неправильный порядок)

 $result = array_intersect_key($array, array_flip($fields)); 

ARRAY_REPLACE (array_intersect_key second): 0.29409 сек (неожиданные результаты: дополнительные значения)

 $result = array_replace( array_fill_keys($fields, false), array_intersect_key($array, array_flip($fields)) ); 

ARRAY_REPLACE (два файла array_intersect_key): 0.33311 sec

 $flip = array_flip($fields); $result = array_replace( array_intersect_key($flip, $array), array_intersect_key($array, $flip) ); 

ARRAY_WALK (set null): 3,35929 с (неожиданные результаты: дополнительные значения)

 function array_walk_filter_by_key_null(&$item, $key, $array) { if (isset($array[$key])) $item = $array[$key]; else $item = null; } $result = array_flip($fields); array_walk($result, 'array_walk_filter_by_key_null', $array); 

ARRAY_REPLACE (сначала array_intersect_key): 11.11044 сек.

 $flip = array_flip($fields); $result = array_intersect_key( array_replace($flip, $array), array_intersect_key($flip, $array) ); 

ARRAY_MERGE: 14.11296 с (неожиданные результаты: дополнительные значения)

 $result = array_splice( array_merge(array_flip($fields), $array), 0, count($fields) ); -во $result = array_splice( array_merge(array_flip($fields), $array), 0, count($fields) ); 

Так оно и есть. Не могу победить DIY. Иногда восприятие заключается в том, что встроенные функции выполняются быстрее, но это не всегда так. В наши дни компиляторы очень хороши.

Я считаю, что это работает так, как вам нужно.

 $result = array_splice(array_merge(array_flip($fields) , $array) , 0 , count($fields)); 

Чтобы решить головоломку:

 $result = array_replace( array_intersect_key(array_flip($fields), $array), array_intersect_key($array, array_flip($fields)) ); 

Первый array_intersect создает список полей в хорошем порядке, другой – с помощью функции array_replace, чтобы создать ключи, которые не существуют в первом массиве.

Отвечает вашим требованиям. Но я бы не использовал его в любом производственном коде, поскольку это может быть довольно тяжелым (я не тестировал, так что это всего лишь ощущение кишки). Решение array_walk кажется легче.

Если вы хотите сохранить порядок ключей из $fields , вы можете попробовать следующее: (если ключ не существует в $array , тогда значение для этого ключа будет равно null.)

 $result = array_flip($fields); array_walk($result, function(&$item, $key, $array) { $item = isset($array[$key]) ? $array[$key] : null; }, $array); var_dump($result); 

Я буду считать, что вы не можете изменить ввод (ни $ array, ни $ fields).

Это может быть достигнуто, если у вас есть массив, который использует в качестве ключей значения из полей $. После этого вы можете объединить два (с $ полями, являющимися первым параметром) и удалить дополнительные элементы.

Учитывая, что вы не можете изменить $ fields, я создам его:

 $tmp = array_combine($fields, range(1, count($fields))); $result = array_merge($tmp, $array); $result = array_splice($result, 0, count($fields)); 

Полный рабочий образец (с некоторыми комментариями) можно найти здесь: http://codepad.org/H0CDN7ok

Моя попытка:

  array_replace( array_fill_keys($fields, false), array_intersect_key($array, # Keys in array, without order array_flip($fields)))); 

Легко было получить ключи в том же порядке, что и $ array. Затем, чтобы получить их в правильном порядке, я построил массив с ключами, равными $ полям. Остальное оставило Array_replace.

Решение «стабильно» в том, что недостающие ключи в массиве $ array будут заменены FALSE и, таким образом, могут быть отфильтрованы, если потребуется.

array_flip ходит массив полей размером N один раз, array_intersect ходит M раз, когда массив размером N, array_fill_keys стоит N, а final array_replace – это, я считаю, N ^ 2.

Таким образом, общая стоимость M * N ^ 5.

Прогуливаясь по самому маленькому массиву и выбирая значения из большого, это O (M ^ 2 * N ^ 2), поэтому при больших значениях NI подозревают, что PHP-решение может оказаться быстрее. Это не вводит ключи, которые не находятся в массиве данных.

  $answer = array(); foreach($fields as $fld) // N-sized cycle if (isset($array[$fld])) // Cost M $answer[$fld] = // Assignment is N*1/2 $array[$fld]; // Getting value is another M 

(спустя некоторое время и много озадачен)

Я проверил чек, и я думаю, что я должен совершить какую-то глупую ошибку, потому что время, которое я получаю, абсолютно бессмысленно. По общему признанию, я использую очень короткий массив $ fields, поэтому я бы ожидал искаженных результатов, но не искажал. Если $ answer [$ fld] вычисляется с помощью некоторого ДЕЙСТВИТЕЛЬНО умного хеш-трюка, согласно которому истинная стоимость интерпретируемого решения не является O (M ^ 2 * N ^ 2), а O (K * N ^ 2) с K малой.

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

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

  $array = array( 'random' => 1, 'pewpew' => 2, 'temp' => 5, 'xoxo' => 3, 'qweqweqe' => 4, ); $fields = array('random', 'xoxo', 'temp'); // Let's not print anything just yet, maybe that's what screwing the timer? $results = ''; $duh = 0; for ($cycle = 0; $cycle < 10; $cycle++) { // Add some more elements to $array. for ($i = 0; $i < 10000; $i++) { $k = uniqid(); $array[$k] = 42; } $start = explode(' ', microtime()); // WTF? Do more cycles to average the timing. for ($j = 0; $j < 10; $j++) { // 0 or 1 to switch if (1) { // INTERPRETED ANSWER $answer = array(); foreach($fields as $fld) // N-sized cycle if (isset($array[$fld])) // Cost M $answer[$fld] = // Assignment is N*1/2 $array[$fld]; // Getting value is another M } else { // FUNCTION ANSWER $answer = array_replace( array_fill_keys($fields, false), // array_combine($fields, $fields), array_intersect_key($array, # Keys in array, without order array_flip($fields))); } // USE $answer so to avoid premature optimization? // You can't be that clever. $duh += strlen(serialize($answer)); } $stop = explode(' ', microtime()); // An error in timing? Check via a stupid roundabout. $int = $stop[1]-$start[1]+1; $int += ($stop[0]-$start[0]); $int -= 1; $elapsed = number_format($int * 1000000, 2); $results .= "".(5000*$cycle)." = $elapsed us.\n"; } // I need to get in result: $wanted = array( 'random' => 1, 'xoxo' => 3, 'temp' => 5, ); // DID we get the right answer? print "Wanted:\n"; print_r($wanted); print "Gotten:\n"; print_r($answer); print "Results: $results\n$duh -- count of array is " . count($array); // And yet I have always the same realtime, name of a dog, how can that be? // I must be doing something REALLY REALLY wrong somewhere. 

Простой способ:

 $array = array( 'random' => 1, 'pewpew' => 2, 'temp' => 5, 'xoxo' => 3, 'qweqweqe' => 4, ); $fields = array('random', 'xoxo', 'temp'); $output = array(); foreach ($fields as $value) if(isset($array[$value])) $output[$value]=$array[$value]; 

Это решение, которое также обрабатывает случай, когда некоторые $fields не присутствуют в виде ключей в $array :

 $flip = array_flip($fields); $result = array_intersect_key(array_replace($flip, $array), array_intersect_key($flip, $array)); 

Если известно, что все $fields присутствуют как ключи в $array это более простое решение:

 $flip = array_flip($fields); $result = array_intersect_key(array_replace($flip, $array), $flip); 

который можно записать как однострочный:

 $result = array_intersect_key(array_replace($flip=array_flip($fields), $array), $flip); 

Если некоторые $fields не являются ключами из $array , но $array содержит counts, так что имеет смысл вернуть 0 счет для отсутствующих ключей, мы можем заменить flip() на array_fill_keys($fields, 0) :

 $result = array_intersect_key(array_replace($fill=array_fill_keys($fields, 0), $array), $fill); 

к которому мы можем применить array_filter() чтобы отфильтровать 0 с, если это необходимо. Заменяя 0 на false или null мы можем отмечать и обрабатывать отсутствие ключа в $array когда значения не считаются.

Печально то, что эти решения, как и все остальные на этой странице, должны работать через все ключи $array , в то время как любой явный цикл будет на $fields . В настоящее время кажется, что когда count($array) намного больше, чем count($fields) решение на основе массива не существует так быстро, как явный цикл (поскольку они явно конструируют результат в функциях обратного вызова, Я рассматриваю array_walk() и array_reduce() как явные петли здесь).

Проблема в том, что ни одна из доступных функций array_ разрушает связь между ключами и значениями, и поскольку мы хотели бы зациклиться на $fields или, вернее, перевернутом массиве, также сохранить свой порядок сортировки, сохраняя при этом значения $array , нам не повезло.

Функция PHP называется array_diff_key .

Образец кода:

 $array = array( 'random' => 1, 'pewpew' => 2, 'temp' => 5, 'xoxo' => 3, 'qweqweqe' => 4 ); $fields = array('random', 'xoxo', 'temp'); $result = array_diff_key($fields, $array); 

Это даст желаемый результат.

Демо: http://shaquin.tk/experiments/array1.php

EDIT: если $fields может содержать значение, которое не является ключом в $array , используйте этот код:

 $result = array_diff_key($fields, $array); $result = array_intersect_key(array_flip($fields), $array); $result = array_flip(array_diff(array_keys($result), $array)); $result = array_replace($result, $array); $result = array_flip(array_intersect(array_flip($result), $fields)); 

Возможно, это будет возможно немного оптимизировать, но оно работает!

Примечание. Я не могу ссылаться на пример, поскольку у моего (размещенного) сайта нет> = PHP 5.3, однако я могу ссылаться на аналогичный: http://shaquin.tk/experiments/array2.php .

пытаться:

 $result=array(); reset($fields); while(list($key,$value)=each($fields)) { if(isset($array[$value])) $result[$value]=$array[$value]; } в $result=array(); reset($fields); while(list($key,$value)=each($fields)) { if(isset($array[$value])) $result[$value]=$array[$value]; } 

Это будет работать и сохранить порядок для вас:

 $fields = array_flip($fields); array_merge($fields,array_intersect_key($array, $fields)); $fields = array_keys($fields); 

заметьте, вы могли бы просто вызвать array_flip дважды, но выше показалось немного «более чистым».