Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Перемешать два массива
 
 автор: Eugene77   (22.04.2012 в 12:14)   письмо автору
 
 

В РНР вроде много удобных функций, но вот для такой простой задачки не могу подобрать удобоваримого решения:

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

  Ответить  
 
 автор: confirm   (22.04.2012 в 12:19)   письмо автору
 
   для: Eugene77   (22.04.2012 в 12:14)
 

Ну так наверное надо пример тогда привести.
А в общем случае, это shuffle и array_combine.

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 12:55)   письмо автору
 
   для: 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 - это совсем другое.

  Ответить  
 
 автор: confirm   (22.04.2012 в 13:13)   письмо автору
 
   для: 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($c0count($a));
print_r($c);

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 13:36)   письмо автору
 
   для: confirm   (22.04.2012 в 13:13)
 

>То есть, тут только одна закономерность - это размер результирующего массива должен быть равен размеру исходных?
>И почему shuffle другое?

Нет, к сожалению, есть и второе обязательное требование.
Элементы массивов должны сохранять свои позиции.

n-й элемент нового массива является либо n-м элементом первого родительского массива, либо n-м элементом второго родительского массива. Никаких перемещений с места на место!

  Ответить  
 
 автор: confirm   (22.04.2012 в 13:52)   письмо автору
 
   для: 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);

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 14:13)   письмо автору
 
   для: 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, когда элементом массива будет являться другой массив (а у меня это часто).
Как вы думаете?

  Ответить  
 
 автор: confirm   (22.04.2012 в 14:23)   письмо автору
 
   для: Eugene77   (22.04.2012 в 14:13)
 

Писали, но что это должно означать, если вы писали еще, что массивы сложные?
Массив конечно же не может быть ключом, так что тут и отвечать собственно нечего. Нужно знать конкретную структуру массивов, чтобы решить задачу, иначе...

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 14:36)   письмо автору
 
   для: confirm   (22.04.2012 в 14:23)
 

Нужно знать конкретную структуру массивов, чтобы решить задачу
Это неизвестно. Структура массивов довольно разнообразна. (Около 20 разных структур), поэтому отдельно для каждого свою функцию писать нерационально.

В принципе, вложенность не очень велика, не более 4-х ступеней.
Сам на себя или на свои элементы массив не ссылается.
Все элементы массива - числа с плавающей точкой.
Индексы либо целые числа (обычно в натуральном порядке), либо строковые константы.
Кажется всё. Больше никаких описаний массива не могу придумать.

  Ответить  
 
 автор: confirm   (22.04.2012 в 14:45)   письмо автору
 
   для: Eugene77   (22.04.2012 в 14:36)
 

>Индексы либо целые числа (обычно в натуральном порядке), либо строковые константы.

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

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 14:52)   письмо автору
 
   для: confirm   (22.04.2012 в 14:45)
 

>Не имея представления о всевозможных структурах ваших массивов, согласитесь, трудно что либо написать.
Я в той же ситуации, что и вы, тоже не могу сообразить, как написать.
Это должна быть достаточно универсальная функция, которая и со строковыми и с натуральными числами в качестве индексов давала бы правильный результат.

Я тоже не в состоянии удержать в голове все структуры массивов или выделить какие-то ещё их особенности структуры, кроме тех, которые уже описал.

  Ответить  
 
 автор: confirm   (22.04.2012 в 14:57)   письмо автору
 
   для: Eugene77   (22.04.2012 в 14:52)
 

Могут ли два массива источника иметь одинаковые строковые ключи?

PS. Забыл отметить в ответе ранее о array_flip. В примере ведь получается индексный массив, значениями которого являются ключи исходного массива, так что в данном случае проблем нет:

$c = array_rand(array_keys($a), 4);
$c = array_flip($c);

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 15:17)   письмо автору
 
   для: confirm   (22.04.2012 в 14:57)
 

>Могут ли два массива источника иметь одинаковые строковые ключи?

Что значит "могут ли"?
Их структура полностью идентична, все ключи полностью одинаковы.
Отличие только в элементах.

  Ответить  
 
 автор: confirm   (22.04.2012 в 15:28)   письмо автору
 
   для: Eugene77   (22.04.2012 в 15:17)
 

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

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 15:23)   письмо автору
 
   для: 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);

  Ответить  
 
 автор: confirm   (22.04.2012 в 15:33)   письмо автору
 
   для: Eugene77   (22.04.2012 в 15:23)
 

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

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 15:40)   письмо автору
 
   для: confirm   (22.04.2012 в 15:33)
 

берем ключи любого из исходных массивов и по ним сортируем или формируем результирующий массив.

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

  Ответить  
 
 автор: confirm   (22.04.2012 в 15:49)   письмо автору
 
   для: Eugene77   (22.04.2012 в 15:40)
 

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

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 16:20)   письмо автору
 
   для: confirm   (22.04.2012 в 15:49)
 

>Зачем рекурсивно. И что значит прошлась по вложенным - они что тоже при формировании нового массива должны каким либо образом меняться?

Как бы это наглядно объяснить?
Я представляю массив в виде дерева.
Каждое ответвление - это вложенный массив.
Он тоже имеет ответвления - другие вложенные массивы.

Конечные элементы - числа с плавающей точкой - листья.
Именно их надо перемешать.
Если у нас есть 2 дерева: одно с красными листьями, другое с жёлтыми,
то надо получить третье - у него часть листьев взята с первого дерева, часть со второго и пересажена на точно те же места на точно тех же веточках.
Такое вот пёстрое дерево ;-)

P.S. Ваша мысль мне ясна, по крайней мере в общих чертах. Но, кажется, она не будет работать с элементами-массивами - она будет перемешивать сразу целые ветки, а не листья.

  Ответить  
 
 автор: confirm   (22.04.2012 в 16:39)   письмо автору
 
   для: 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($marray_key_exists($k$a
                                           ? 
array_intersect_key($a, array($k=>1)) 
                                           : 
array_intersect_key($b, array($k=>1)));
print_r($m);

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 16:51)   письмо автору
 
   для: 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];
}

Какой код будет быстрей работать?

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

  Ответить  
 
 автор: confirm   (22.04.2012 в 17:04)   письмо автору
 
   для: Eugene77   (22.04.2012 в 16:51)
 

А при чем тут этот код? Вам же надо получить тот же порядок, что и в исходном массиве, а ключи то ведь раскиданы по обеим массивам, и порядок их отличен от исходных. В моем приеме массив C хранит порядок, в вашем примере что-то случайное.

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 17:48)   письмо автору
 
   для: confirm   (22.04.2012 в 17:04)
 

>А при чем тут этот код? Вам же надо получить тот же порядок, что и в исходном массиве, а ключи то ведь раскиданы по обеим массивам, и порядок их отличен от исходных. В моем приеме массив C хранит порядок, в вашем примере что-то случайное.
Разве? Мне казалость, что в массиве $c должен получиться ровно тот же порядок, что и в массиве $a.
Тогда подскажите как произойдёт его нарушение?

  Ответить  
 
 автор: confirm   (22.04.2012 в 18:05)   письмо автору
 
   для: Eugene77   (22.04.2012 в 17:48)
 

Ну я же в примере изменяю оба исходных массива. )
Массив А в процессе становиться лишь случайной частью самого себя, а массив В его остатком. По массиву С, который сохраняет порядок ключей исходных массивов строим результирующий массив. Если первый ключ массива С находится в массиве А, то берем элемент из этого массива по этому ключу, в противном случае берем такой элемент в массиве В. Полученный элемент добавляем в массив М, и так до конца.

Я так понимаю, что перемешать вложения, это сделать с ними тоже самое, что и с первичными ключами? Рекурсия конечно, и, если это возможно, лучше иметь не два массива, а один, каждое вложение которого, это два массива описывающие два набора. При обходе такого массива, это будет лучше.

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 18:17)   письмо автору
 
   для: confirm   (22.04.2012 в 18:05)
 

>Ну я же в примере изменяю оба исходных массива. )

Цикл, который я написал полностью заменяет ваш код, а не частично.

Итоговую задачу он, конечно, не решает, но ту упрощённую, к которой вы свели - вроде решает.
Хоть он и очень медленный, раз нельзя сделать без циклов на функциях, то тогда он вроде лучше.

  Ответить  
 
 автор: confirm   (22.04.2012 в 18:22)   письмо автору
 
   для: Eugene77   (22.04.2012 в 18:17)
 

Тогда да.

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 19:05)   письмо автору
 
   для: confirm   (22.04.2012 в 18:22)
 

Ещё раз спасибо за обсуждение!
Приятно поговорить с человеком, хорошо знающим функции!
И полезно, - теперь я знаю в каком направлении дальше продожать разработку.

  Ответить  
 
 автор: confirm   (22.04.2012 в 19:07)   письмо автору
 
   для: Eugene77   (22.04.2012 в 19:05)
 

Еще вопрос - то есть получается так, перемешиваются вложения, а по первичным ключам нет?

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 20:45)   письмо автору
 
   для: confirm   (22.04.2012 в 19:07)
 

>Еще вопрос - то есть получается так, перемешиваются вложения, а по первичным ключам нет?
Мне непонятно что такое первичный ключ - это ж не SQL :-)

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

  Ответить  
 
 автор: confirm   (22.04.2012 в 20:52)   письмо автору
 
   для: Eugene77   (22.04.2012 в 20:45)
 

Да, самый верхний его уровень, корневые ключи.
Ясно, просто думал как обходить именно сам корень массива.

  Ответить  
 
 автор: Valick   (22.04.2012 в 12:46)   письмо автору
 
   для: Eugene77   (22.04.2012 в 12:14)
 

всегда уточняйте откуда у вас эти массивы?

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 12:57)   письмо автору
 
   для: Valick   (22.04.2012 в 12:46)
 

>всегда уточняйте откуда у вас эти массивы?

Хм, как откуда? Создаю

  Ответить  
 
 автор: Valick   (22.04.2012 в 13:20)   письмо автору
 
   для: Eugene77   (22.04.2012 в 12:57)
 

создавать можно руками, приняв данные от пользователя, и при выборке из базы

  Ответить  
 
 автор: Eugene77   (22.04.2012 в 13:26)   письмо автору
 
   для: Valick   (22.04.2012 в 13:20)
 

>создавать можно руками, приняв данные от пользователя, и при выборке из базы
Не, массивы не из базы, в базе массивы со вложенными подмассивами неудобно хранить.

Есть специальные функции, которые создают эти массивы (написал вручную)

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования