Логика заполнения двумерного массива PHP

12 3
D
На сайте с 28.06.2008
Offline
1101
180

Есть двумерный массив из 317 подмассивов. В этих подмассивах последовательность нулей и единиц (могут быть одни нули, а могут и содержать некоторые кол-во едениц).

Задача собрать новый двумерный массив по следующей логике:

Начать в цикле добавлять подмассивы в новый массив, если подряд идут только с нулями, то склеиваем их  один, пока не попадется подмассив с единицей.

Их мы тоже начинаем склеивать вместе. И т.д.

Т.е. было так

$oldArray = [
0=>{0,0,0 ...одни нули},
1=>{0,0,0 ...одни нули},
2=>{0,0,0 ...одни нули},
3=>{0,0,0 ...одни нули},
4=>{0,0,1 ...есть единица},
5=>{0,1,0 ...есть единица},
6=>{1,0,0 ...есть единица},
7=>{0,0,0 ...одни нули},
8=>{0,0,0 ...одни нули},
]

стало

$newArray = [
0=>{0,0,0 ...одни нули (склеиваем подмассивы где только нули и которые идут подряд)},
1=>{0,0,1 ...есть единица (склеили подмассивы в которых есть единица и которые идут подряд},
2=>{0,0,0 ...одни нули (склеиваем подмассивы где только нули и которые идут подряд)},
]

Уже несколько часов мучаюсь не могу придумать как сие организовать.

По идее нужно как-то так

for($i=0;$i<317;$i++){
   
    if(!in_array(1,$tempArr[$i])){
       
    }

    if(in_array(1,$tempArr[$i])){
      
    }
}

Но так и не домучал, array_merge + array_push кручу верчу по разному, не получается...

Алеандр
На сайте с 08.12.2010
Offline
183
#1

Dram :

Уже несколько часов мучаюсь не могу придумать как сие организовать.

перебор старого массива
для первого вхождения задать базовый вход, временную контрольную переменную равную 1 или 0, определив if (in_array) единицу или ее отсутствие, после добавив к новому массиву этот первый подмассив
затем, при проходе дальше по старому массиву проверяешь также, 1 или 0, есть или нет в подмассиве
если совпадает с уже текущим значением проверки, то merge с последним элементом нового массива
если же не совпадает, переназначить текущую переменную проверки и добавить новый элемент нового массива

проверил, нет единиц, поставил переменную ноль, добавил в новый
проверил следующий, нет единиц - склеил с последним добавленным в новом
проверил следующий, есть единица - сменил переменную контроля и добавил как новый элемент

Алеандр
На сайте с 08.12.2010
Offline
183
#2
prevtmp=2;
foreach oldarray
if in_array(1,subarr) { tmp=1} else { tmp=0 }
if tmp!=prevtmp {
newarr[] = subarr; prevtmp = tmp }
else {
array_merge subarr+last elem newarr }
D
На сайте с 28.06.2008
Offline
1101
#3

Спасибо, переписал так

$tmp = 0;
$prevtmp=2;
$newArr = [];

for
($i=0;$i<317;$i++){

    if (in_array(1,$tempArr[$i]) )
    {
        $tmp=1;
    }
    else {
        $tmp=0 ;
    }
    if ($tmp!=$prevtmp) {
        $newArr = $tempArr[$i];
        $prevtmp = $tmp;
    }
    else {
        array_merge ($tempArr[$i],$newArr[count($newArr)-1]);
    }

}

В итоге получил массив и 317 подмассивов. Или я ошибся или логика неверная.

T7
На сайте с 19.09.2018
Offline
63
#4
Dram #:
array_merge ($tempArr[$i],$newArr[count($newArr)-1])
$oldArray = [
  0=>[0,0,0],
  1=>[0,1,0],
  2=>[0,0,0],
  3=>[0,1,0],
];

$new_a = [
  0=>[],
  1=>[],
];

foreach($oldArray as $k=>$v){
  if(!in_array(1, $v))
    $new_a[0] = array_merge ($new_a[0], $v);
  else
    $new_a[1] = array_merge ($new_a[1], $v);
    
}
Array
(
    [0] => Array
        (
            [0] => 0
            [1] => 0
            [2] => 0
            [3] => 0
            [4] => 0
            [5] => 0
        )

    [1] => Array
        (
            [0] => 0
            [1] => 1
            [2] => 0
            [3] => 0
            [4] => 1
            [5] => 0
        )

)
Алеандр
На сайте с 08.12.2010
Offline
183
#5
Dram #:

Спасибо, переписал так

В итоге получил массив и 317 подмассивов. Или я ошибся или логика неверная.

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

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

Алеандр
На сайте с 08.12.2010
Offline
183
#6

Судя по его варианту, как должно быть:

$newArray = [
0=>{0,0,0 ...одни нули (склеиваем подмассивы где только нули и которые идут подряд)},
1=>{0,0,1 ...есть единица (склеили подмассивы в которых есть единица и которые идут подряд},
2=>{0,0,0 ...одни нули (склеиваем подмассивы где только нули и которые идут подряд)},
]

ваш вариант не подойдет, ибо он соберет все только в 2 массива, а ему нужно свести только пограничные.

T7
На сайте с 19.09.2018
Offline
63
#7
Алеандр #:
ваш вариант не подойдет

А ну да, ну да. Был невнимателен. Прошу понять и простить

for($i=0;$i<$l;$i++){
  if(!in_array(1, $oldArray[$i])) {
    if($tmp[0]===0) { #значит предыдущий - только нули
      $new_a[0][$tmp[1]] = $oldArray[$tmp[1]]; #чтобы учесть предыдущий, если он учтен, то будет просто переписан
      $new_a[0][$i] = $oldArray[$i];
    }
    $tmp = [0, $i]; #первый элемент 0 если только нули, второй ссылка на индекс элемента
    #если нужен
    #$new_a[3][$i] = $oldArray[$i];
  }  else {
    if($tmp[0]===1)  {
      $new_a[1][$tmp[1]] = $oldArray[$tmp[1]];
      $new_a[1][$i] = $oldArray[$i];
    }
    $tmp = [1, $i];
  }
}
D
На сайте с 28.06.2008
Offline
1101
#8
timo-71 #:

А ну да, ну да. Был невнимателен. Прошу понять и простить

Спасибо за помощь - все равно не то.

Вот начало полученного массива, он трехуровневый

array(2) {
  [0]=>
  array(81) {
    [2]=>
    array(51) {
      [0]=>
      int(2)
      [1]=>
      int(0)
      [2]=>
      int(0)
      [3]=>
      int(0)
.....
и его конец
....








} [312]=> array(51) { [0]=> int(312) [1]=> int(0) [2]=> int(0)

Каждый подмассив 3-го уровня длинной 50 (как и у исходного). + непонятно растущий первый элемент каждого подмассива (зачеркнул), он увеличивается 

А нужен массив 2-х уровневый который по идее (в результате склейки) будет иметь подмассивы разной длинны.


Может ошибся где?

$tmp = 0;
$new_a = [];

for($i=0;$i<317;$i++){
    if(!in_array(1, $tempArr[$i])) {
        if($tmp[0]===0) { #значит предыдущий - только нули
            $new_a[0][$tmp[1]] = $tempArr[$tmp[1]]; #чтобы учесть предыдущий, если он учтен, то будет просто переписан
            $new_a[0][$i] = $tempArr[$i];
        }
        $tmp = [0, $i]; #первый элемент 0 если только нули, второй ссылка на индекс элемента
        #если нужен
        #$new_a[3][$i] = $oldArray[$i];
    }  else {
        if($tmp[0]===1)  {
            $new_a[1][$tmp[1]] = $tempArr[$tmp[1]];
            $new_a[1][$i] = $tempArr[$i];
        }
        $tmp = [1, $i];
    }
}

вот это не понял

if($tmp[0]===0)

какой индекс - это же переменная, не массив?

Anamnado
На сайте с 08.02.2010
Offline
242
#9
Dram :
Уже несколько часов мучаюсь

мало!

приходи с вопросом после 2х недель.....

[не шучу.]

думаю что дней через 3-5 помощь нужна уже не будет. 

T7
На сайте с 19.09.2018
Offline
63
#10
Dram #:
какой индекс - это же переменная, не массив?
$tmp = 0;

У меня такого нет. А, не с начала вставил😞

$l = count($oldArray);
$tmp = [false];
for($i=0;$i<$l;$i++){
....
 $tmp = [1, $i];

Если есть 1 то первый элемент 1, если нет, то 0. Расти ничего не должно, т.к. 

$new_a[0][$i] = $tempArr[$i];

просто добавляется элемент исходного массива.

Но, все равно задачу не верно понял. Между делом, одним глазом. И 2 косяка с пониманием задачи. Надо в санаторий😅


$tmp0 = [];
$tmp1 = [];

function _a(array &$a, array &$b, array $c){
  foreach($c as $v){
    $a = array_merge($a, $b[$v]);
  }
}

for($i=0;$i<$l;$i++){
  if(!in_array(1, $oldArray[$i])) {    
    if(count($tmp1)>1)  {
      _a($new_a[1], $oldArray, $tmp1);
    }
    array_push($tmp0, $i); #соберем индексы массива, если там нет единиц
    $tmp1 = [];
  }  else {    
    if(count($tmp0)>1) {
#если индексов больше одного, что значит подряд, сольем в $new_a[0]
      _a($new_a[0], $oldArray, $tmp0);
    }
    array_push($tmp1, $i);
    $tmp0 = []; #обнулим массив индексов

  }
}

var_dump($new_a);
12 3

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий