PHP - как сделать merge по key + value?
Массив:
array(2) {
[0]=> array(2) {
["2020-03-27"]=> int(8)
["tags"]=> string(17) "STS; сервис" }
[1]=> array(2) {
["2020-03-27"]=> int(3)
["tags"]=> string(17) "PTP; сервис; тест" }
}
Как лучше собрать новый массив, в котором если такой ключ уже есть (например ['2020-03-27']), то
- Объединить элемент массива с ключем
["tags"], но если его значение одинаковое - то сделатьmerge, если нет - добавить новые значения. - Значение элемента с ключем
["2020-03-27"]- установить последнее.
Я бы сделал так: проверяем есть ли такой ключ, если есть - обновляем значение , а вот как быть с ["tags"] пока не пойму лучше.
Т.е должен получиться вот такой массив:
array(1) {
[0]=> array(2) {
["2020-03-27"]=> int(3)
["tags"]=> string(17) "STS; PTP; сервис; тест" }
}
Ответы (3 шт):
Автор решения: Denis640Kb
→ Ссылка
Всё немного сложнее, так как значение tags у Вас является строкой, и надо сравнивать значения в строке.
Добавил решение и постарался добавить больше комментариев для понимания работы скрипта:
<?php
$arr = array(
array(
"2020-03-27" => 8,
"tags" => "STS; сервис"
),
array(
"2020-03-27" => 3,
"tags" => "PTP; сервис; тест"
),
array(
"2020-03-17" => 3,
"tags" => "PTP; сервис; тест"
)
);
$Result = []; // Сюда запишем результат
foreach ($arr as $val){ // Для каждого элемента массива
$keys = array_keys($val); // Получаем ключи
$firstKey = $keys[0]; // Берём первый ключ условно (2020-03-27)
if ($Result){ // Если есть массив
$z = explode('; ', $val['tags']); // Разбиваем поле tags по точке с запятой и пробелу, чтобы получить значение
foreach ($Result as $key=>$item){ // Для каждого элемента массива результата...
$trig = 1; // проставляем триггер
$keys1 = array_keys($item); // Получаем так же ключи
$firstKey1 = $keys1[0]; // берём первый ключ
if ($firstKey == $firstKey1) { // Проверяем совпадение ключей, если совпадают, то...
$z1 = explode('; ', $item['tags']); // Разбиваем значение tags
$temp = array_merge($z, $z1); // Сливаем 2 массива
$temp1 = array_unique($temp); // Оставляем только уникальные значения
$tags = implode('; ', $temp1); // Соединем обратно в строку
$Result[$key]['tags'] = $tags; // Меняем значение в массиве $Result
} else {
$trig = 0; // Если ключи не равны, то меняем триггер.
}
}
if($trig == 0){ // Если триггер изменён, то значит ключи не равны, а значит...
$Result[] = $val; // Добавляем значение в массив
}
} else {
$Result[] = $val; // Если массив $Result пуст, то добавляем значение
}
}
print_r($Result); // Выводим результат.
Автор решения: Pavel
→ Ссылка
Предложу вариант покороче.
<?php
$arr = array(
array(
"2020-03-27" => 8,
"tags" => "STS; сервис; 27"
),
array(
"2020-03-27" => 3,
"tags" => "PTP; сервис; тест"
),
array(
"2020-03-17" => 3,
"tags" => "PTP; сервис; тест; 17"
)
);
$result = [];
foreach($arr as $element){
// получаем дату из ключа
list($date, ) = array_keys($element);
// если уже есть с такой датой
if(isset($result[$date])){
// строим строку
$tags = $result[$date]['tags'].'; '.$element['tags'];
// убираем повторы через преобразование в массив и обратно
$tags = implode("; ",array_unique(explode("; ",$tags)));
}else{
$tags = $element['tags'];
}
$result[$date] = [
$date => $element[$date],
'tags' => $tags
];
}
// убираем дату из ключей если нужно
$result = array_values($result);
print_r($result);
Автор решения: UKRman
→ Ссылка
<?php
$array = [
[
"2020-03-27" => 8,
"tags" => "STS; сервис"
],
[
"2020-03-27" => 3,
"tags" => "PTP; сервис; тест"
],
[
"2020-03-17" => 3,
"tags" => "PTP; сервис; тест"
]
];
$result = [];
foreach($array as &$item) {
$key = key($item);
$hikings = array_filter(
$array,
function ($item) use ($key) {
if (key($item) === $key) {
return $item;
}
}
);
$map = $item;
foreach($hikings as $index => $hiking) {
$map[$key] = $hiking[$key];
$map['tags'] = implode(';', array_unique(array_merge(explode(';', $map['tags']), explode(';', $hiking['tags']))));
unset($array[$index]);
}
$result[] = $map;
}
var_dump($result);