Check for coherency in an array? - php

I have an array with elements like this:
1_elem1
2_elem2
3_elem3
Now I want to check if something in that structure is out of place. Out of place means:
The numbers in front are not succeeding
Numbers are missing
Whats the shortest way to do that in PHP? I thought of sorting the array and check if each element starts with a number. That would solve 2. I am not sure how to do 1. though.

If you can solve the 2nd problem, then you could check if the number is equivalent to the index of the array, taking into account the number of missing numbers up to that point.
Meaning that, the index of each element should be equal to the number in front.
Except when there has been a number missing in the past elements, but if you take that into account, you could include a incrementor and subtract that value.

That's a kind of combination of both arrays and regular expressions.
<?php
$arr = array( // here is our array
"1_elem1",
"4_elem2", // here is an unexpected value
"3_elem3"
);
$arr = array_values($arr); // if our array has custom keys change it to consecutive numbers
try {
array_walk($arr, function($val, $key)
{
$key++; // add 1 to the index ( because starts at 0)
$pattern = "#".$key."_elem".$key."#"; // write down our pattern
if(!preg_match($pattern, $val))
{
throw new Exception("Not in sequence: ".$val, 1); // if not in sequence then throw an error
}
});
echo "Array has sequential values";
} catch (Exception $e) {
echo $e;
die();
}

Since you asked for "shortest", how about:
function check($array) {
for ($i = count($array)-1; 0 < $i; $i--)
if (1 !== ((int)$array[$i] - (int)$array[$i-1]))
return false;
return true;
}
Start at the end walking backward, compute difference between this and previous element, if not exactly one return false. Otherwise return true. Note the typecast to int is simple way to get leading digits.

Related

How to determine if an array contains anything but a specific value?

Given the below array of values, what is the best way to determine if the array contains anything other than the value 4?
$values = [1,2,3,4,5,6];
For clarity, I don't want to check that 4 simply doesn't exist, as 4 is still allowed to be in the array. I want to check the existence of any other number.
The only way I can think to do it is with a function, something like the below:
function checkOtherValuesExist(array $values, $search) {
foreach ($values as $value) {
if ($value !== $search)
return TRUE;
}
}
}
Simply do array_diff to get array without 4's
$diff = array_diff($values, [4]);
if (!empty($diff)) {
echo "Array contains illegal values! "
. "Legal values: 4; Illegal values: " . implode(', ', $diff);
} else {
echo "All good!";
}
TBH - I think your current version is the most optimal. It will potentially only involve 1 test, find a difference and then return.
The other solutions (so far) will always process the entire array and then check if the result is empty. So they will always process every element.
You should add a return FALSE though to make the function correct.

Multidimensional sub array subtraction in PHP

Need subarray difference of below array
$arr = array(
array('s'=>'1','e'=>'3'),
array('s'=>'6','e'=>'7'),
array('s'=>'8','e'=>'9'),
array('s'=>'10','e'=>'14'),
array('s'=>'16','e'=>'17'),
)
if(arr[$arr[$i+1][s] - $i][e] <= 1){
//join them
}
else {
//save them as it is
}
Desired result should
$arr = array(
array('s'=>'1','e'=>'3'),
array('s'=>'6','e'=>'14'),
array('s'=>'16','e'=>'17'),
)
No consecutive (next S-E) should be 1
http://codepad.org/V8omMdn6 is where im struck at
See its like
iteration 0
6-3 = 3
so save array('s'=>'1','e'=>'3'),
iteration 1
8-7 = 1
array('s'=>'6','e'=>'9'), => discade in 2 as it
iteration 2
10-9 = 1
array('s'=>'6','e'=>'10'), => discade in 3 as it
iteration 3
10-9 = 1
array('s'=>'6','e'=>'14'),
iteration 4
16-14 = 4
array('s'=>'16','e'=>'17'),
$result = [];
foreach ($arr as $pair) {
if (empty($result) || $pair['s'] - end($result)['e'] > 1) {
$result[] = $pair;
} else {
$result[key($result)]['e'] = $pair['e'];
}
}
You might also use $last as key instead end() & key() for readability.
Using array pointer functions on $result shortens the code but uses some ugly hidden effects. end($result) returns last element of array (using key bracket with function result is possible since php5.3 I guess), but also sets the pointer, so key($result) will return correct key if needed.
While iterating you process last element of result array - this element might not be valid right away, but you don't need to look ahead. There are two scenarios for last element (+initial state condition for empty $result):
invalid: set e value from current item and process further
valid: leave it and push current item into results for further validation (unless that was the last one).
I took a very brief look at your codepen, I think what you want to achieve is to find out if the start time of a new session is within a given period from the end time of the last session, if so you would like to combine those sessions.
I think you confused yourself by trying to subtract start time of new session from end time of last session, it should be the other way round.
The way you worded the question made it even more confusing for people to understand.
If my interpretation of your question is correct, the below code should work with the test case you posted here.
function combineSession($arr){
$arrCount=count($arr)-1;
for ($i=0; $i<$arrCount; $i++){
//if the difference between s and e is less than or equal to one, then there is a consecutive series
if($arr[$i+1]['s']-$arr[$i]['e'] <= 1){
//assign the value of s at the start of a consecutive series to $temp
if (!isset($temp)){
$temp=$arr[$i]['s'];
}
//if consecutive series ends on the last sub_array, write $temp e pair to output
if ($i==$arrCount-1){
$output[]= array('s'=> $temp, 'e' => $arr[$arrCount]['e']);
}
}
//end of a consecutive series, write $temp and e pair to output, unset $temp
else if (isset($temp) && $i<$arrCount-1){
$output[]=array('s'=> $temp, 'e' => $arr[$i]['e']);
unset($temp);
}
//consecutive series ended at the second last sub-array, write $temp and e pair to output and copy key value pair of the last sub-array to output
else if ($i==$arrCount-1){
$output[]=array('s'=> $temp, 'e' => $arr[$i]['e']);
$output[]=$arr[$arrCount];
}
//not in a consecutive series, simply copy s e key value pair to output
else {
$output[]=$arr[$i];
}
}//end of for loop
print_r($output);
}//end of function
else if ($i==$arrCount-1){ $output[]=!isset($temp) ? $arr[$i] : array('s'=> $temp, 'e' => $arr[$i]['e']); $output[]=$arr[$arrCount]; }

Compare variable start with array key

There is this array:
$array1 = array(51=>1.1, 45=>68, 57=>43, 62=>35, 74=>24);
And I want to verify if the value that is taken from the variable starts with any of the keys from the array. (the variable is passing correctly, I checked that)
foreach (array_keys($array1) as $key1) {
if(preg_match("/^[$rvalue]/", $key1))
{
$positive1=true;
$fvalue1=$array1[$key1];
}
else{
$positive1=false;
}
}
The problem is that it runs all the array and always gives me the value of the last key, instead of one matching the variable.
I'm new with regex, so might be that, don't know. Any help is appreciated.
Seems kind of complicated for a simple task. How about at direct comparison:
foreach ($array1 as $key1 => $value) {
if (substr($rvalue, 0, strlen($key1)) == $key1)
{
$fvalue1 = $value;
break;
}
}
Just break from the loop when you find a match.
Get rid of the square brackets in the regexp. Also, you're doing the check backwards -- you want to put the keys into the regexp, and match that against the string:
if (preg_match("/^$key1/, $rvalue))
Square brackets in a regexp are used to match a single character that's any one of the characters in the bracket. So [51] matches 5 or 1, but it doesn't match the whole string 51.
You could also combine all the keys into a single regexp, using | in the regexp to specify alternatives:
$alternatives = implode('|', array_keys($array1));
if (preg_match("/^(?:$alternatives)/", $rvalue, $match)) {
$positive1 = true;
$fvalue1 = $array1[$match[0]];
} else {
$positive1 = false;
}

PHP: Counting elements using for loops

I would like to count numeric values in a group of two for equal values. For example for list of values 1,2,3,3,3,3,3,3,3,3,5,5,6
I should have 1,2,(3,3),(3,3),(3,3),(3,3),(5,5),6
That is when I decide to count the first (3,3) are counted as 1. Therefore in this case I should have $count=8 instead of $count=13 for all values. I have tried to do some for loops and if statements but I get wrong results. Any idea is highly appreciated. Thanks
Note: the pairs have to be adjacent to be regarded as 1.
$list = array(1,2,3,3,3,3,3,3,3,3,5,5,6);
$counter = 0;
foreach($list as $number)
{
if(isset($previous) and $previous === $number)
{
unset($previous);
}
else
{
$previous = $number;
$counter++;
}
}
echo $counter; // 8
Regular expression solution with back references:
$s = '1,2,3,3,3,3,3,3,3,3,5,5,6';
echo count(explode(',', preg_replace('/(\d+),\\1/', '\\1', $s)));
Output:
8
The regular expression matches a number and then uses a back reference to match the number adjacent to it. When both are matched, they are replaced by one number. The intermediate result after the preg_replace is:
1,2,3,3,3,3,5,6
After that, the count is performed on the comma separated values.

Compare All strings in a array to all strings in another array, PHP

What i am trying to do is really but i am going into a lot of detail to make sure it is easily understandable.
I have a array that has a few strings in it. I then have another that has few other short strings in it usually one or two words.
I need it so that if my app finds one of the string words in the second array, in one of the first arrays string it will proceed to the next action.
So for example if one of the strings in the first array is "This is PHP Code" and then one of the strings in the second is "PHP" Then it finds a match it proceeds to the next action. I can do this using this code:
for ( $i = 0; $i < count($Array); $i++) {
$Arrays = strpos($Array[$i],$SecondArray[$i]);
if ($Arrays === false) {
echo 'Not Found Array String';
}
else {
echo 'Found Array String';
However this only compares the First Array object at the current index in the loop with the Second Array objects current index in the loop.
I need it to compare all the values in the array, so that it searches every value in the first array for the First Value in the second array, then every value in the First array for the Second value in the second array and so on.
I think i have to do two loops? I tried this but had problems with the array only returning the first value.
If anyone could help it would be appreciated!
Ill mark the correct answer and + 1 any helpful comments!
Thanks!
Maybe the following is a solution:
// loop through array1
foreach($array1 as $line) {
// check if the word is found
$word_found = false;
// explode on every word
$words = explode(" ", $line);
// loop through every word
foreach($words as $word) {
if(in_array($word, $array2)) {
$word_found = true;
break;
}
}
// if the word is found do something
if($word_found) {
echo "There is a match found.";
} else {
echo "No match found."
}
}
Should give you the result you want. I'm absolute sure there is a more efficient way to do this.. but thats for you 2 find out i quess.. good luck
You can first normalize your data and then use PHP's build in array functions to get the intersection between two arrays.
First of all convert each array with those multiple string with multiple words in there into an array only containing all words.
A helpful function to get all words from a string can be str_word_count.
Then compare those two "all words" arrays with each other using array_intersect.
Something like this:
$words1 = array_unique(str_word_count(implode(' ', $Array), 1));
$words2 = array_unique(str_word_count(implode(' ', $SecondArray), 1));
$intersection = array_intersect($words1, $words2);
if(count($intersection))
{
# there is a match!
}
function findUnit($packaging_units, $packaging)
{
foreach ($packaging_units as $packaging_unit) {
if (str_contains(strtoupper($packaging[3]), $packaging_unit)) {
return $packaging_unit;
}
}
}
Here First parameter is array and second one is variable to find

Categories