Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / PHP, Perl, Python Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 PHP - поменять ключ в массиве  [new]
Alibek B.
Member

Откуда:
Сообщений: 2990
Можно ли в существующем массиве изменить ключ элемента?
Такое разумеется не сработало:
$k = '123';
$v = &$k;
$a = [$v=>&$v];
print_r([$k,$v,$a]);

$k = '321';
print_r([$k,$v,$a]);

Ну а [&$v=>&$v] не компилируется.
Есть какие-нибудь обходные способы?
Пока что наиболее близкое получилось такое:
$new = '321';
$old = '123';
$a[$new] = &$a[$old];
unset($a[$old]);
print_r([$k,$v,$a]);
30 дек 18, 13:16    [21776853]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Karbafos
Member

Откуда:
Сообщений: 454
зачем?
31 дек 18, 00:38    [21777063]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
полудух
Member

Откуда: планета орков, г.Зверополис
Сообщений: 489
$map['newkey'] = $map['oldkey'];
unset($map['oldkey']);


в компах нет никакой "магии"
всё есть "последовательность байтов" (из 0/1), а на нижнем уровне просто набор инструкций - куда чего в памяти переместить/посчитать
31 дек 18, 03:05    [21777071]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Hett
Member

Откуда: Бийск, Новосибирск
Сообщений: 13435
полудух,

ТС такой же вариант написал, и даже лучше.
31 дек 18, 08:34    [21777090]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
полудух
Member

Откуда: планета орков, г.Зверополис
Сообщений: 489
Hett
полудух,

ТС такой же вариант написал, и даже лучше.

это?
автор
$a[$new] = &$a[$old];
unset($a[$old]);

рановато вы праздновать начали Картинка с другого сайта.
31 дек 18, 08:51    [21777091]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
полудух
Member

Откуда: планета орков, г.Зверополис
Сообщений: 489
или это: $a = [$v=>&$v]; Картинка с другого сайта.

зы: а ещё у него в 2 раза больше строк
31 дек 18, 08:53    [21777092]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Alibek B.
Member

Откуда:
Сообщений: 2990
полудух
$map['newkey'] = $map['oldkey'];
unset($map['oldkey']);


Так себе решение.
Такой способ очевиден, он далеко не лучший.
31 дек 18, 19:22    [21777209]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
vkle
Member

Откуда: Самара
Сообщений: 14520
Alibek B.
он далеко не лучший
В каком отношении не лучший и почему, что конкретно в этом способе плохо?
31 дек 18, 19:36    [21777215]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Alibek B.
Member

Откуда:
Сообщений: 2990
а) Не сохраняет порядок элементов.
б) Копирует элемент массива вместо копирования ссылки на элемент.
31 дек 18, 21:41    [21777234]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
полудух
Member

Откуда: планета орков, г.Зверополис
Сообщений: 489
вы удаляете этот элемент, какая ещё ссылка
31 дек 18, 21:47    [21777235]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
vkle
Member

Откуда: Самара
Сообщений: 14520
Alibek B.,

а) Ну дык порядок и не должен сохраняться при такой операции. Об этом где-то в инструкции по PHP сказано. Другой вопрос, если такое поведение PHP, как изменение порядка элементов, не подходит для конкретной Вашей задачи. Тут уж, звиняйте. Но оно никак не отвечает на вопрос о том, что плохо в этом способе или что хорошо.

б) Об этом (клонирование или дублирование фрагмента памяти, содержащего данные) где-то явно сказано или Вы смотрели исходники PHP в части манипуляций с элементами массива?
31 дек 18, 22:24    [21777246]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Alibek B.
Member

Откуда:
Сообщений: 2990
полудух
вы удаляете этот элемент, какая ещё ссылка

Это заблуждение.
unset не удаляет содержимое элемента.
31 дек 18, 23:23    [21777252]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Alibek B.
Member

Откуда:
Сообщений: 2990
vkle
Об этом (клонирование или дублирование фрагмента памяти, содержащего данные) где-то явно сказано

http://php.net/manual/ru/language.references.whatdo.php
31 дек 18, 23:25    [21777253]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Alibek B.
Member

Откуда:
Сообщений: 2990
vkle
Но оно никак не отвечает на вопрос о том, что плохо в этом способе или что хорошо.

Мне - отвечает.
Вопрос был в том, как поменять ключ.
При чистом изменении ключа сам массив меняться не должен, равно как порядок элементов.
31 дек 18, 23:29    [21777257]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
vkle
Member

Откуда: Самара
Сообщений: 14520
Alibek B.
vkle
Об этом (клонирование или дублирование фрагмента памяти, содержащего данные) где-то явно сказано

http://php.net/manual/ru/language.references.whatdo.php
При чем тут ссылки то? Хотя, если хотите использовать ссылки, то там как раз сказано:
обе переменные указывают на одни и те же данные и никакого копирования не происходит

Однако, раз уж говорим тут о присваивании вида $b = $a, то для скалярных переменных - в мануале смотрите тут http://php.net/manual/ru/features.gc.refcounting-basics.php Пример #3. Таки ссылка добавляется.
Для объектов происходит присваивание по ссылке, об этом явно сказано тут: http://php.net/manual/ru/language.operators.assignment.php
Таким образом, насчет копирования Вы ошибаетесь в любом случае.

Alibek B.
При чистом изменении ключа сам массив меняться не должен, равно как порядок элементов.
Вполне возможно, если в ЯП присутствует функция, которая именно так работает. Но, увы. Несмотря на довольно обширный набор функций PHP для работы с массивами http://php.net/manual/ru/book.array.php
1 янв 19, 00:26    [21777262]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
полудух
Member

Откуда: планета орков, г.Зверополис
Сообщений: 489
Alibek B.
полудух
вы удаляете этот элемент, какая ещё ссылка

Это заблуждение.
unset не удаляет содержимое элемента.

http://fi2.php.net/manual/ru/function.unset.php
Пример #1 Пример использования unset()

<?php
// удаляем одну переменную
unset($foo);

// удаляем один элемент массива
unset($bar['quux']);

// удаляем несколько переменных
unset($foo1, $foo2, $foo3);
?>

// удаляем один элемент массива
1 янв 19, 06:15    [21777299]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Alibek B.
Member

Откуда:
Сообщений: 2990
Заблуждение не перестает быть таковым, независимо от количества повторений.

$lazarus = ['a'=>['melchior', 'balthasar', 'casper']];
print_r(['before',$lazarus]);
$undead = &$lazarus['a'];
unset($lazarus['a']);
$undead[] = 'wonder';
print_r(['dead',$lazarus]);
$lazarus['b'] = $undead;
print_r(['raising',$lazarus]);

Посоветую читать англоязычную документацию.
И посмотреть в словарях значения слов remove и destroy.
1 янв 19, 08:48    [21777301]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
vkle
Member

Откуда: Самара
Сообщений: 14520
полудух
Alibek B.
пропущено...

Это заблуждение.
unset не удаляет содержимое элемента.

http://fi2.php.net/manual/ru/function.unset.php
Пример #1 Пример использования unset()

<?php
// удаляем одну переменную
unset($foo);

// удаляем один элемент массива
unset($bar['quux']);

// удаляем несколько переменных
unset($foo1, $foo2, $foo3);
?>


// удаляем один элемент массива
Ну, с Новым годом!
Элемент массива (ссылка на область памяти, где хранится значение) и содержимое элемента массива (область памяти, выделенная для хранения значения) совсем не одно и то же. Вы можете удалить элемент из массива или удалить переменную, но очисткой памяти от неиспользуемых данных занимается механизм Garbage Collection, он же сборщик мусора. Если он включен, конечно.
1 янв 19, 11:22    [21777310]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
полудух
Member

Откуда: планета орков, г.Зверополис
Сообщений: 489
Alibek B.
Заблуждение не перестает быть таковым, независимо от количества повторений.

$lazarus = ['a'=>['melchior', 'balthasar', 'casper']];
print_r(['before',$lazarus]);
$undead = &$lazarus['a'];
unset($lazarus['a']);
$undead[] = 'wonder';
print_r(['dead',$lazarus]);
$lazarus['b'] = $undead;
print_r(['raising',$lazarus]);


Посоветую читать англоязычную документацию.
И посмотреть в словарях значения слов remove и destroy.

вы укуренный чтоли там ещё в добавок Картинка с другого сайта.
нахрена вы копируете $lazarus['a'] в отдельную переменную,
а затем эту переменную ставите в $lazarus['b] ?!?
и вуаля - ФОКУС ГОТОВ! Картинка с другого сайта.
при этом $lazarus['a'] там, как и положено, благополучно удалён unset-ом Картинка с другого сайта.

зы: и можете даже ссылку убрать - эффект тот же.

vkle
Ну, с Новым годом!
Элемент массива (ссылка на область памяти, где хранится значение) и содержимое элемента массива (область памяти, выделенная для хранения значения) совсем не одно и то же. Вы можете удалить элемент из массива или удалить переменную, но очисткой памяти от неиспользуемых данных занимается механизм Garbage Collection, он же сборщик мусора. Если он включен, конечно.

угу, счастья, здоровья...
а вдруг прогер внезапно пишет на C++ и САМ удаляет всё за собой? Картинка с другого сайта.

в пхп таки есть ГЦ, но это неважно
Удалён он там физически или ждём ГЦ, а в массиве его уже нет после unset().
1 янв 19, 12:06    [21777317]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Alibek B.
Member

Откуда:
Сообщений: 2990
полудух
зы: и можете даже ссылку убрать - эффект тот же.

Смешной ты и необразованный.
$a1 = ['a'=>[1,2,3]];
$a2 = ['a'=>[11,22,33]];
$r1 = $a1['a'];
$r2 = &$a1['a'];
$a1['a'][] = 999;
$a2['a'][] = 999;
unset($a1['a'],$a2['a']);
$a1['b'] = $r1;
$a2['b'] = $r2;
unset($r1,$r2);
print_r([$a1,$a2]);


Array
(
[0] => Array
(
[b] => Array
(
[0] => 1
[1] => 2
[2] => 3
)

)

[1] => Array
(
[b] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 999
)

)

)
1 янв 19, 12:14    [21777318]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Дормедонт Евлампиевич
Member

Откуда:
Сообщений: 81
function array_change_key(&$array, $src, $dst)
{
    $keys = array_keys($array);
    $i = array_flip($keys)[$src];
    $keys[$i] = $dst;
    $array = array_combine($keys, $array);
}


Alibek B., я думаю, Вы бы и самостоятельно додумались до такого грубого решения. Но если так, почему такие вопросы?
1 янв 19, 15:04    [21777338]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Alibek B.
Member

Откуда:
Сообщений: 2990
Не до такого, как вариант с сохранением порядка элементов я думал использовать range с последующим combine.
Но и это опять же не замена ключа в массиве, а формирование нового массива.
Мне интересно именно изменить ключ. Может быть есть такой способ, просто я его не знаю, так как PHP я использую от случая к случаю и утилитарно.
1 янв 19, 15:27    [21777341]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Alibek B.
Member

Откуда:
Сообщений: 2990
Что касается задачи, то я пишу скрипт-сервис (работающий как демон), который взаимодействует с внешней системой.
В этом скрипте есть вспомогательный справочник (массив), используемый для быстрого поиска данных пользователей по номеру телефона (номер телефона - ключ). Но в информационной системе у пользователей номер телефона может меняться и в этом случай справочник нужно обновить. При этом по определенным причинам хотелось бы сохранить порядок элементов в справочнике.
1 янв 19, 15:33    [21777343]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
полудух
Member

Откуда: планета орков, г.Зверополис
Сообщений: 489
Alibek B.
полудух
зы: и можете даже ссылку убрать - эффект тот же.

Смешной ты и необразованный.

а ты тупой, как воробушек.
в примере опят unset() отработал именно так, как и должен был Картинка с другого сайта.
а именно - удалил элементы массива.
надежды на то, что он сотрёт r2 вместе со ссылкой опять же подчёркивают полную безграмотность вопрошающего юнца (даже если допустить, что вместо &$a1 там &$a2)
очень хочется верить, что эти "гениальные" примеры перерастут во что-то стоящее ДО следующего нового года.

Alibek B.
Что касается задачи, то я пишу скрипт-сервис (работающий как демон), который взаимодействует с внешней системой.
В этом скрипте есть вспомогательный справочник (массив), используемый для быстрого поиска данных пользователей по номеру телефона (номер телефона - ключ). Но в информационной системе у пользователей номер телефона может меняться и в этом случай справочник нужно обновить. При этом по определенным причинам хотелось бы сохранить порядок элементов в справочнике.

потому что БД лишний раз дёргать не хочется
ты ещё и коллега, студент Картинка с другого сайта.
причина тут одна - неопытный дурачок кастует самому себе (и людям, что гораздо важнее) палки в колёсах
парсеры иди пиши, а не ИФ, твоя архитектура - говно.
Модератор: За своими словами следите, пожалуйста.
1 янв 19, 16:53    [21777363]     Ответить | Цитировать Сообщить модератору
 Re: PHP - поменять ключ в массиве  [new]
Karbafos
Member

Откуда:
Сообщений: 454
Alibek B.
Что касается задачи, то я пишу скрипт-сервис (работающий как демон), который взаимодействует с внешней системой.
В этом скрипте есть вспомогательный справочник (массив), используемый для быстрого поиска данных пользователей по номеру телефона (номер телефона - ключ). Но в информационной системе у пользователей номер телефона может меняться и в этом случай справочник нужно обновить. При этом по определенным причинам хотелось бы сохранить порядок элементов в справочнике.


Ты не можешь сохранить порядок элементов в хэше, никак, это как запрос select из базы без order by, порядок не гарантируется.
Тем более, что при перестроении списка ключей связи меняются.
Поиск по ключу хеша это O(1), ему пофиг на порядок, он итак быстрый.

Сравни вывод для
<?php

$a = [
    '012' => '012',
    '123' => '123',
    '456' => '456'
];

$new = '321';
$old = '123';
$a[$new] = &$a[$old];
unset($a[$old]);

print_r($a);


и

<?php

$a = [
    '012' => '012',
    '123' => '123',
    '456' => '456'
];

$new = '321';
$old = '123';
$a[$new] = $a[$old];
unset($a[$old]);

print_r($a);


Они идентичны.

Не нужно без повода использовать &

Вот пример опкодов для

$a[$new] = &$a[$old];

line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
11 3 FETCH_DIM_W $7 !0, !2
4 MAKE_REF $8 $7
5 FETCH_DIM_W $6 !0, !1
6 ASSIGN_REF $6, $8

и

$a[$new] = $a[$old];

line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
11 3 FETCH_DIM_R $7 !0, !2
4 ASSIGN_DIM !0, !1
5 OP_DATA $7

Второй более оптимален в таком варианте.
1 янв 19, 17:24    [21777369]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / PHP, Perl, Python Ответить