Answer the question
In order to leave comments, you need to log in
How to avoid a nested loop and do it in a humane way?
Good afternoon!
I rack my brains, leafing through the function reference, I can’t think of anything better ...
There are 2 arrays: the original one is $data, and the array of new data is $new_data.
The goal is, if the values of the two keys match, to replace the old data with the new ones.
You also need to know which elements of the new data did not match in the original.
There are more keys in the real array of initial data.
An easy way is nested loops. But, both arrays can have 1000 elements each ... My poor knowledge is not enough to do it humanly. Tell me how to optimize it?
//исходные данные
$data[] = array("a" => 'art1', "b" => '10');
$data[] = array("a" => 'art2', "b" => '20');
$data[] = array("a" => 'art3', "b" => '30');
$data[] = array("a" => 'art4', "b" => '40');
$data[] = array("a" => 'art5', "b" => '50');
$data[] = array("a" => 'art6', "b" => '60');
//новые данные
$new_data[] = array("a" => 'art1', "b" => '15');
$new_data[] = array("a" => 'art2', "b" => '25');
$new_data[] = array("a" => 'art3', "b" => '35');
foreach($data as $index => $data_val) //для каждого элемента исходных данных
foreach($new_data as $nk => $new_val) //перебираем новые данные
if($data_val["a"]===$new_val["a"]){ //если значения ключей совпали
$data[$index]["b"]=$new_val["b"]; //меняем значение
break; //дальше не ищем
}
print_r($data);
/*
Вот такой должен быть результат:
Array (
[0] => Array ( [a] => art1 [b] => 15 )
[1] => Array ( [a] => art2 [b] => 25 )
[2] => Array ( [a] => art3 [b] => 35 )
[3] => Array ( [a] => art4 [b] => 40 )
[4] => Array ( [a] => art5 [b] => 50 )
[5] => Array ( [a] => art6 [b] => 60 )
)
*/
Answer the question
In order to leave comments, you need to log in
$notFound = array();
foreach ($new_data as $k => $v)
{
if (isset($data[$k])) $data[$k] = $v;
else $notFound[$k] = $v;
}
You need an index.
Those. move the "key" field to the array index. If there is more than one key field, serialize.
those.
$dataToGo=[]; foreach($data as $entry) $dataToGo['$entry['key']]=$entry;
Do you have the ability to turn both arrays into associative arrays with a key on the 'a' field?
Array (
[art1] => Array ( [b] => 15 )
[art2] => Array ( [b] => 25 )
[art3] => Array ( [b] => 35 )
)
$data = array_replace_recursive($data, $new_data);
php.net/manual/ru/function.array-merge.php
If the input arrays have the same string keys, then each subsequent value will replace the previous one. However, if the arrays have the same numeric keys, the value mentioned last will not replace the original value, but will be added to the end of the array.
$intersect = array_intersect_key($new_data, $data); //массив с одинаковыми ключами
array_merge($data, $intersect); //перезаписываем старые значения новыми
$diff = array_diff_key($new_data, $intersect); //получаем массив с элементами, которых нет в $data
The fastest way is to sort both arrays by key, and then iterate over both arrays with two pointers (comparing the entries and moving the pointers manually). In addition, when I did this and tested it (for a long time, on version 5.1 somewhere), pointers worked 2 times faster than for / foreach.
You need to make a an array index and use array_intersect_key/array_diff_key to find duplicate entries. Then there will be almost no cycles.
Here's for PHP 5.5:
//исходные данные
$data[] = array("a" => 'art1', "b" => '10');
$data[] = array("a" => 'art2', "b" => '20');
$data[] = array("a" => 'art3', "b" => '30');
$data[] = array("a" => 'art4', "b" => '40');
$data[] = array("a" => 'art5', "b" => '50');
$data[] = array("a" => 'art6', "b" => '60');
//новые данные
$new_data[] = array("a" => 'art1', "b" => '15');
$new_data[] = array("a" => 'art2', "b" => '25');
$new_data[] = array("a" => 'art3', "b" => '35');
$new_data = array_column($new_data, 'b', 'a');
foreach($data as &$v) //для каждого элемента исходных данных
if (isset($new_data[$v["a"]])); //если найдены новые данные
$v["b"] = $new_data[$v["a"]]; //меняем значение
unset($new_data[$v["a"]]); //экономим память
}
unset($v);
print_r($data);
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question