2015-08-12 4 views
3

Допустим, у нас есть эти массивы:Сравнение массивов и компактным, если в том же порядке

$a = array("B", "C", "D", "E"); 
$b = array("A", "B" , "C", "D", "E", "F", "G", "H", "I"); 

Тогда я хочу, чтобы проверить, является ли последовательность к югу от $a последовательна в $b. Если да, и это более трех элементов, я хочу вывести их с тире, например. X-Y. Во всех остальных случаях я просто хочу распечатать значения, разделенные запятой.

Так ожидаемый выход из приведенного выше $a массива будет:

B-E 

Другой пример:

$a = array("B", "C", "D", "F", "H"); 
//Same $b array to check if a sub sequence of $a appears in $b consecutive 

Ожидаемый результат:

B-D, F, H 

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

Я чувствую, что мне не хватает чего-то очевидного, и это очень простая вещь.

Редактировать: Вот мой текущий прогресс.

$pointer = count($b); 
$a = array("B", "C" , "D", "E"); 
$b = array("A", "B", "C" , "D", "E", "F", "G"); 

foreach ($b as $key => $bb) { 
    if ($a[0] == $bb) { 
     $pointer = $key; 
    } 
} 


$d = array(); 
$d[] = $a[0]; 
foreach ($a as $key => $aa) { 
    if ($aa == $b[$pointer+$key]) { 
     $pointer = $key; 
    } else { 
     $d[] = "-".$aa; 
     $pointer++; 
    } 
} 
echo implode('',$d); 

Edit 2: Значения являются не только буквы. Они являются строками и могут иметь разную длину. («AA», «b», «lk»).

+2

* Я пробовал некоторые сумасшедшие Еогеасп * Покажите нам, что сумасшедший код, и мы покажем вы, как заставить этот сумасшедший код работать – Rizier123

+1

Непонятно, что именно вы хотите, хотите ли вы пропустить любое конкретное значение или несколько значений? быть очень ясным, пожалуйста, – M3ghana

+1

@ Rizier123 Я добавил код, который я пытался сделать после того, как я сдался на петлях. – Cheppa

ответ

3

Это должно работать для вас:

Просто цикл через весь массив и в каждой итерации просто напечатать текущее значение итерации.

Затем в цикле while проверьте, есть ли еще следующий элемент массива или нет с isset() И если текущий элемент массива равен следующему.

Это можно сделать, получив значение ASCII символа с помощью ord() и добавьте его, прежде чем сравнивать его.

Если вы равны на то, что вы увеличиваете $i и $followUp.

После цикла вы можете проверить, если у вас есть более чем 1 символ, которые следуют в очередной текущей (.eg: A, D = 0 следуют вверх, A, B, D = 1 следуют вверх; A, B, C = 2 follow up). И если у вас больше 1, вы печатаете это значение с тире между ними.

Затем, если это не конец массива, также напечатайте запятую, чтобы отделить значения.

В конце цикла for просто проверьте, не было ли у вас только 1 последующего действия и отмените приращение $i + сброс $followUp, назначив 0.

<?php 

    $a = array("A", "B", "C", "F", "H", "K", "L", "M", "N", "R", "S", "X", "Y", "Z"); 

    $length = count($a); 
    $followUp = 0; 
    for($i = 0; $i < $length; $i++) { 

     echo $a[$i]; 

     while(isset($a[$i+1]) && (ord($a[$i]) + 1) == ord($a[$i+1])){ 
      ++$followUp; 
      ++$i; 
     } 

     if($followUp > 1) 
      echo "-" . $a[$i]; 

     if($i != count($a) - 1) 
      echo ","; 

     if($followUp == 1) --$i; 
     $followUp = 0; 

    } 

?> 

выход:

A-C,F,H,K-N,R,S,X-Z 

EDIT:

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

Только implode() массив поиска и проверьте с помощью strpos(), если вспомогательный массив, который вы можете получить с помощью array_slice(), а также взорваться в строке, находится в массиве поиска.

<?php 

    $a = array("A", "B", "C", "F", "H", "K", "L", "M", "N", "R", "S", "X", "Y", "Z"); 
    $b = array("A", "B" , "C", "D", "E","F", "H", "M", "N", "R", "S", "F", "G", "H", "I", "M", "N", "R", "S"); 

    $length = count($a); 
    $followUp = 0; 
    for($i = 0; $i < $length; $i++) { 

     echo $a[$i]; 
     $current = $i; 
     while(isset($a[$i]) && strpos(implode("|", $b), implode("|", array_slice($a, $current, $followUp+1))) !== FALSE){ 
      ++$followUp; 
      ++$i; 
     } 

     if($followUp > 2) 
      echo "-" . $a[--$i]; 

     if($i != count($a) - 1) 
      echo ","; 

     if($followUp <= 2) $i = $current; 
     $followUp = 0; 

    } 

?> 

выход:

A-C,F,H,K,L,M-S,X,Y,Z 
+0

Все, вы избили меня, чтобы использовать ord. – user2072826

+0

, и я случайно сделал это в JS, так что мой ответ бесполезен. – user2072826

+0

Удивительный ответ для моего вопроса. Хотя я должен был добавить, что значения в массиве могут быть любыми: («b», «FF», «12», «a»); поэтому он будет показывать «FF-a» для («FF», «12», «a») – Cheppa

0

Попробуйте это решение. Он имеет только один цикл.

$a = array("A", "B", "C", "F", "H", "K", "L", "M", "N", "R", "S", "X", "Y", "AA", "AB", "AC", "AD"); 
$d = []; 

$isFollow = false; 

foreach($a as $el){ 
    if (count($d) == 0){ 
     $d[] = $el; 
     continue; 
    } 

    $next = $d[count($d) - 1]; 
    $next++; 

    if ($el == $next){ 
     $isFollow ? $d[count($d) - 1] = $el : $d[] = $el; 
     $isFollow = true; 
    } else { 
     if ($isFollow){ 
      $d[count($d) - 2] .= "-".$d[count($d) - 1]; 
      $d[count($d) - 1] = $el; 
     } else $d []= $el; 

     $isFollow = false; 
    } 
} 

if ($isFollow){ 
    $d[count($d) - 2] .= "-".$d[count($d) - 1]; 
    unset($d[count($d) - 1]); 
} 

echo implode(',', $d); 

Выход

A-C, F, H, K-N, R-S, X-Y, AA-AD 

Вы можете написать свой метод сравнения последовательных элементов вместо

$next = $d[count($d) - 1]; 
$next++; 
if ($el == $next) 
Смежные вопросы