检查数组

时间:2018-04-25 13:02:20

标签: php arrays

我正在寻找一种循环关联数组的方法,但只能在之前的5"状态"是" CLOSED_FOR_SERVICE"以及接下来的5"状态"是" OPEN"

这是我提出的有效的方法,但到目前为止并不优雅。我确信我需要为前一个使用for循环,然后为下一个使用另一个循环,但我似乎无法理解它。

$logRow data

for ($i = 0; $i < count($logRow); $i++) {
    if (array_key_exists($i - 1, $logRow)){
        if (($logRow[$i]['status'] == "OPEN") && ($logRow[$i - 1]['status'] == "CLOSED_FOR_SERVICE")){
            if (array_key_exists($i - 2, $logRow)){
                if ($logRow[$i - 2]['status'] == "CLOSED_FOR_SERVICE"){
                    if (array_key_exists($i - 3, $logRow)){
                        if ($logRow[$i - 3]['status'] == "CLOSED_FOR_SERVICE"){
                            if (array_key_exists($i - 4, $logRow)){
                                if ($logRow[$i - 4]['status'] == "CLOSED_FOR_SERVICE"){
                                    if (array_key_exists($i - 5, $logRow)){
                                        if ($logRow[$i - 5]['status'] == "CLOSED_FOR_SERVICE"){
                                            if (array_key_exists($i + 1, $logRow)){
                                                if ($logRow[$i + 1]['status'] == "OPEN"){
                                                    if (array_key_exists($i + 2, $logRow)){
                                                        if ($logRow[$i + 2]['status'] == "OPEN"){
                                                            if (array_key_exists($i + 3, $logRow)){
                                                                if ($logRow[$i + 3]['status'] == "OPEN"){
                                                                    if (array_key_exists($i + 4, $logRow)){
                                                                        if ($logRow[$i + 4]['status'] == "OPEN"){
                                                                            if (array_key_exists($i + 5, $logRow)){
                                                                                if ($logRow[$i + 5]['status'] == "OPEN"){
                                                                                    echo date("F j, Y, g:i a", $logRow[$i]['time']).'<br />';
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

5 个答案:

答案 0 :(得分:1)

我没有时间对此进行测试(我会尽快尝试),但这是一般性的想法:

for($i = 0; $i < count($logRow); $i++) {
    if($logRow[$i]['status'] == 'OPEN' &&
       ($prev = array_slice($logRow, $i - 6, 5)) &&
       ($next = array_slice($logRow, $i + 1, 5)) &&
       !array_diff(array_column($prev, 'status'), ['CLOSED_FOR_SERVICE']) &&
       !array_diff(array_column($next, 'status'), ['OPEN']))
    {
            echo date("F j, Y, g:i a", $logRow[$i]['time']).'<br />';
    }
}
  • 循环并检查当前status是否已打开
  • 切片前5个元素
  • 切片接下来的5个元素
  • 从之前的5中提取status元素并检查与CLOSED_FOR_SERVICE无差异
  • 从下一个5中提取status个元素,并检查与OPEN无差异

可能更好,只有一个array_column调用整个数组,除非它是巨大的。

答案 1 :(得分:1)

这是我的想法 不要循环整个阵列。从5开始,在count-4结束,因为在此之前和之后你不会有足够的项目是真的。

Array_slice十个项目并与&#34;模式数组&#34;进行比较。

// i used 0 or 1 instead of closed or open but the idea is the same.
$arr = [0,0,0,1,0,0,1,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1];
for($i = 5; $i<count($arr)-4;$i++){
    if([0,0,0,0,0,1,1,1,1,1] == array_slice($arr, $i-5, 10)){
        //echo date("F j, Y, g:i a", $logRow[$i]['time']).'<br />';
        echo "yes\n";
    }
}

https://3v4l.org/m4K7m

答案 2 :(得分:1)

只是为了好玩,以为我会加入,但做一些完全不同的事情。而不是试图匹配数组而不必担心环绕(如果传递负数,某些数组方法会拾取数组的末尾),我决定尝试匹配字符串......

$mangle = implode(",", array_column($logRow, "status"));
$toFind = trim(str_repeat("CLOSED_FOR_SERVICE,", 5).str_repeat("OPEN,", 5), ",");

$offset = 0;
while ( ($offset = strpos($mangle, $toFind, $offset )) !== false)   {
    $index = substr_count(substr($mangle, 0, $offset), ",");
    $index = array_keys($logRow)[$index+5];    // I do this because I extracted part of the sample data
    echo date("F j, Y, g:i a", $logRow[$index]['time']).PHP_EOL;
    $offset++;
}

因此它构建了一个包含所有状态的字符串,然后查找5个CLOSED_FOR_SERVICE的字符串,然后查找5个OPEN的字符串。然后它会将逗号计数到它找到此模式的点(添加5,因为这包括5个CLOSED_FOR_SERVICE记录)。

它重复循环,从它停止的地方继续(++确保它不会再次找到相同的那个)。

如果您有一个完整的数组,则不需要array_keys(),但正如我在评论中提到的,我提取了部分数据,因此有非顺序键。

答案 3 :(得分:-1)

你走了。

for ($i = 5; $i < count($logRow) - 5; $i++) {
    $prev = array_slice($logRow, $i - 5, 5);
    $next = array_slice($logRow, $i + 1, 5);

    if (
        5 === count(array_filter($prev, function($row) {
            return 'CLOSED_FOR_SERVICE' === $row['status'];
        }))

        &&

        5 === count(array_filter($next, function($row) {
            return 'OPEN' === $row['status'];
        }))
    ) {
        echo date('F j, Y, g:i a', $logRow[$i]['time']).'<br />';
    }
}

答案 4 :(得分:-1)

/* =============================
 * PSEUDO CODE 
 * ============================= 
 */

// Initialize
open = 0
closed = 0
out = null
//Loop
foreach (array as line) {
  // Test for CLOSED_FOR_SERVICE 5 times consecutive occurences
  if (closed == 4) {
      // Capture target time and jump to next line
      if (out == null) {
         out = line[time]
         continue
      }
      // Start testing for OPEN statuses and count or reinitialize
      if (line[status] == 'OPEN') {
         open = open + 1
      } else {
         out = null
         open = 0
         closed = 0
         continue
      }

      // Bingo
      if (open == 4) {
         print out
         out = null
         open = 0
         closed = 0
      }
  } else {
      // Count CLOSED_FOR_SERVICE or reinitialize
      closed = line[status] == 'CLOSED_FOR_SERVICE' ? closed + 1 : 0
  }

}