|
|
|
| В РНР вроде много удобных функций, но вот для такой простой задачки не могу подобрать удобоваримого решения:
Надо создать массив из двух других.
При этом в новом массиве каждый из элементов должен быть взят из соответстующей позиции одного из массивов.
Массивы, разумеется, все одинаковые по структуре, но довольно сложно устроенные (со вложенностью).
Чередование должно происходить в случайном порядке. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 12:14)
| | Ну так наверное надо пример тогда привести.
А в общем случае, это shuffle и array_combine. | |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 12:19)
| | >Ну так наверное надо пример тогда привести.
>А в общем случае, это shuffle и array_combine.
Мне надо из
{1,2,3,4,5,6,7} и
{8,9,0,0,0,0,0}
Получить:
{1,9,3,0,0,0,7}
Если один из элементов массива - тоже массив, то там такая же мешанина должна выйти.
shuffle и array_combine - это совсем другое. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 12:55)
| | То есть, тут только одна закономерность - это размер результирующего массива должен быть равен размеру исходных?
И почему shuffle другое?
<?
$a = array(1,2,3,4,5,6,7);
$b = array(8,9,0,0,0,0,0);
$c = array_merge($a, $b);
shuffle($c);
$c = array_slice($c, 0, count($a));
print_r($c);
|
| |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 13:13)
| | >То есть, тут только одна закономерность - это размер результирующего массива должен быть равен размеру исходных?
>И почему shuffle другое?
Нет, к сожалению, есть и второе обязательное требование.
Элементы массивов должны сохранять свои позиции.
n-й элемент нового массива является либо n-м элементом первого родительского массива, либо n-м элементом второго родительского массива. Никаких перемещений с места на место! | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 13:36)
| | Вы частями свои условия выдаете...
<?
$a = array(1,2,3,4,5,6,7);
$b = array(8,9,0,0,0,0,0);
$c = array_rand(array_keys($a), 4);
$c = array_flip($c);
$a = array_diff_key($a, $c);
$b = array_intersect_key($b, $c);
$c = $a + $b;
ksort($c);
print_r($c);
|
| |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 13:52)
| | >Вы частями свои условия выдаете...
Неправда. Я с самого начала написал:
"каждый из элементов должен быть взят из соответстующей позиции одного из массивов"
>
<?
>$a = array(1,2,3,4,5,6,7);
>$b = array(8,9,0,0,0,0,0);
>$c = array_rand(array_keys($a), 4);
>$c = array_flip($c);
>$a = array_diff_key($a, $c);
>$b = array_intersect_key($b, $c);
>$c = $a + $b;
>ksort($c);
>print_r($c);
|
Замечательный код!
Только мне кажется, что будут проблемы с array_flip, когда элементом массива будет являться другой массив (а у меня это часто).
Как вы думаете? | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 14:13)
| | Писали, но что это должно означать, если вы писали еще, что массивы сложные?
Массив конечно же не может быть ключом, так что тут и отвечать собственно нечего. Нужно знать конкретную структуру массивов, чтобы решить задачу, иначе... | |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 14:23)
| | Нужно знать конкретную структуру массивов, чтобы решить задачу
Это неизвестно. Структура массивов довольно разнообразна. (Около 20 разных структур), поэтому отдельно для каждого свою функцию писать нерационально.
В принципе, вложенность не очень велика, не более 4-х ступеней.
Сам на себя или на свои элементы массив не ссылается.
Все элементы массива - числа с плавающей точкой.
Индексы либо целые числа (обычно в натуральном порядке), либо строковые константы.
Кажется всё. Больше никаких описаний массива не могу придумать. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 14:36)
| | >Индексы либо целые числа (обычно в натуральном порядке), либо строковые константы.
Поэтому и нужно представлять ожидаемое, потому как, например, функция array_merge по разному будет поступать с ключи - со строковыми, заменяя одинаковые, а индексные добавляя в конец.
Не имея представления о всевозможных структурах ваших массивов, согласитесь, трудно что либо написать. | |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 14:45)
| | >Не имея представления о всевозможных структурах ваших массивов, согласитесь, трудно что либо написать.
Я в той же ситуации, что и вы, тоже не могу сообразить, как написать.
Это должна быть достаточно универсальная функция, которая и со строковыми и с натуральными числами в качестве индексов давала бы правильный результат.
Я тоже не в состоянии удержать в голове все структуры массивов или выделить какие-то ещё их особенности структуры, кроме тех, которые уже описал. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 14:52)
| | Могут ли два массива источника иметь одинаковые строковые ключи?
PS. Забыл отметить в ответе ранее о array_flip. В примере ведь получается индексный массив, значениями которого являются ключи исходного массива, так что в данном случае проблем нет:
$c = array_rand(array_keys($a), 4);
$c = array_flip($c);
|
| |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 14:57)
| | >Могут ли два массива источника иметь одинаковые строковые ключи?
Что значит "могут ли"?
Их структура полностью идентична, все ключи полностью одинаковы.
Отличие только в элементах. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 15:17)
| | Ну собственно принцип решения можно оставить таким же - получаем из первого разность ключей, а из второго совпадающие (или наоборот), и формируем результирующий массив. Вот только при смешанных ключах (индексы и строки) отсортировать его уже так не получиться. Первое, что приход в этом случае, это сформировать массив массивов ключей исходных массивов, обходя его, находить соответствие им в результирующем массиве, таким образом отсортировав его. | |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 14:57)
| | Пример:
$a['data'] = 4;
$a['coef'] = array_fill(0, 7,1);
$a = array_fill(0, 4, $a);
|
$b['data'] = 5;
$b['coef'] = array_fill(0, 7,2);
$b = array_fill(0, 4, $b);
|
| |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 15:23)
| | Понятно, тогда поправка по сортировке - берем ключи любого из исходных массивов и по ним сортируем или формируем результирующий массив. | |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 15:33)
| | берем ключи любого из исходных массивов и по ним сортируем или формируем результирующий массив.
ммм... что-то не въеду никак... это ведь должна быть функция, которую можно вызывать рекурсивно.
Недостаточно, чтобы она вместо элемента-массива подставила один из массивов, надо чтобы она и по вложенным массивам прошлась. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 15:40)
| | Зачем рекурсивно. И что значит прошлась по вложенным - они что тоже при формировании нового массива должны каким либо образом меняться? Что-то совсем запутано.
Смысл решение задачи предложенный мною ведь прост - взять из первого массива случайную часть, взять из второго массива остаток. Все это с учетом первичных ключей массивов.
В примере массивы индексные, а посему сложение с последующей сортировкой по ключам все решало.
При смешанных ключах такое сделать будет невозможно, а поэтому получаем ключи исходные (любого из массивов, они ведь имеют одинаковые ключи, судя по представленному вами), затем обычным циклом обходим этот массив ключей, выбирая по ним из массивов полученных частей элементы с такими ключами, формируя результирующий массив. | |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 15:49)
| | >Зачем рекурсивно. И что значит прошлась по вложенным - они что тоже при формировании нового массива должны каким либо образом меняться?
Как бы это наглядно объяснить?
Я представляю массив в виде дерева.
Каждое ответвление - это вложенный массив.
Он тоже имеет ответвления - другие вложенные массивы.
Конечные элементы - числа с плавающей точкой - листья.
Именно их надо перемешать.
Если у нас есть 2 дерева: одно с красными листьями, другое с жёлтыми,
то надо получить третье - у него часть листьев взята с первого дерева, часть со второго и пересажена на точно те же места на точно тех же веточках.
Такое вот пёстрое дерево ;-)
P.S. Ваша мысль мне ясна, по крайней мере в общих чертах. Но, кажется, она не будет работать с элементами-массивами - она будет перемешивать сразу целые ветки, а не листья. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 16:20)
| | Сначала был вопрос как получить массив как случайную комбинацию из двух, и по примеру речь могла идти только о первичных ключах. Теперь оказывается, что внутри еще должно быть перемешано? Если да, то как - забрать элемент у одного ключа и отдать другому?
Лично я уже запутался, что вам надо.
То о чем я говорил, о сортировке, так это примерно так:
<?
$a = array(0=>'1.1',1=>'1.2','asd'=>'1.3',2=>'1.4','cdf'=>'1.5','cvb'=>'1.6',3=>'1.7','bnm'=>'1.8',4=>'1.9');
$b = array(0=>'2.1',1=>'2.2','asd'=>'2.3',2=>'2.4','cdf'=>'2.5','cvb'=>'2.6',3=>'2.7','bnm'=>'2.8',4=>'2.9');
$c = array_flip(array_rand(array_flip(array_keys($a)),5));
$a = array_diff_key($a, $c);
$c = array_flip(array_keys($b));
$b = array_diff_key($b, $a);
$m = array();
foreach($c as $k=>$v) $m = array_merge($m, array_key_exists($k, $a)
? array_intersect_key($a, array($k=>1))
: array_intersect_key($b, array($k=>1)));
print_r($m);
|
| |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 16:39)
| |
<?
foreach($a as$k => $v) {
if(mt_rand(0,2) > 1) $c[$k] = $v;
else $c[$k] = $b[$k];
}
|
Какой код будет быстрей работать?
В любом случае, большое вам спасибо, так как я увидел именно благодаря этому обсуждению, что простого решения задачи на функциях, вероятно, не существует. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 16:51)
| | А при чем тут этот код? Вам же надо получить тот же порядок, что и в исходном массиве, а ключи то ведь раскиданы по обеим массивам, и порядок их отличен от исходных. В моем приеме массив C хранит порядок, в вашем примере что-то случайное. | |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 17:04)
| | >А при чем тут этот код? Вам же надо получить тот же порядок, что и в исходном массиве, а ключи то ведь раскиданы по обеим массивам, и порядок их отличен от исходных. В моем приеме массив C хранит порядок, в вашем примере что-то случайное.
Разве? Мне казалость, что в массиве $c должен получиться ровно тот же порядок, что и в массиве $a.
Тогда подскажите как произойдёт его нарушение? | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 17:48)
| | Ну я же в примере изменяю оба исходных массива. )
Массив А в процессе становиться лишь случайной частью самого себя, а массив В его остатком. По массиву С, который сохраняет порядок ключей исходных массивов строим результирующий массив. Если первый ключ массива С находится в массиве А, то берем элемент из этого массива по этому ключу, в противном случае берем такой элемент в массиве В. Полученный элемент добавляем в массив М, и так до конца.
Я так понимаю, что перемешать вложения, это сделать с ними тоже самое, что и с первичными ключами? Рекурсия конечно, и, если это возможно, лучше иметь не два массива, а один, каждое вложение которого, это два массива описывающие два набора. При обходе такого массива, это будет лучше. | |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 18:05)
| | >Ну я же в примере изменяю оба исходных массива. )
Цикл, который я написал полностью заменяет ваш код, а не частично.
Итоговую задачу он, конечно, не решает, но ту упрощённую, к которой вы свели - вроде решает.
Хоть он и очень медленный, раз нельзя сделать без циклов на функциях, то тогда он вроде лучше. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 18:17)
| | Тогда да. | |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 18:22)
| | Ещё раз спасибо за обсуждение!
Приятно поговорить с человеком, хорошо знающим функции!
И полезно, - теперь я знаю в каком направлении дальше продожать разработку. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 19:05)
| | Еще вопрос - то есть получается так, перемешиваются вложения, а по первичным ключам нет? | |
|
|
|
|
|
|
|
для: confirm
(22.04.2012 в 19:07)
| | >Еще вопрос - то есть получается так, перемешиваются вложения, а по первичным ключам нет?
Мне непонятно что такое первичный ключ - это ж не SQL :-)
Если это ключи корневого массива, то тоже должно быть перемешивание значений с плавающей точкой. Не перемешиваются только массивы между собой, вместо того, чтобы их перемешивать, функция должна идти внутрь массива(являющегося элементом родительского) и перемешивать значения с соответствующим отростком другого массива. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 20:45)
| | Да, самый верхний его уровень, корневые ключи.
Ясно, просто думал как обходить именно сам корень массива. | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 12:14)
| | всегда уточняйте откуда у вас эти массивы? | |
|
|
|
|
|
|
|
для: Valick
(22.04.2012 в 12:46)
| | >всегда уточняйте откуда у вас эти массивы?
Хм, как откуда? Создаю | |
|
|
|
|
|
|
|
для: Eugene77
(22.04.2012 в 12:57)
| | создавать можно руками, приняв данные от пользователя, и при выборке из базы | |
|
|
|
|
|
|
|
для: Valick
(22.04.2012 в 13:20)
| | >создавать можно руками, приняв данные от пользователя, и при выборке из базы
Не, массивы не из базы, в базе массивы со вложенными подмассивами неудобно хранить.
Есть специальные функции, которые создают эти массивы (написал вручную) | |
|
|
|
|