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.
Related
I'm trying to make a simple PHP script for school. I need to output 2 random students from the array $leerlingen (Leerlingen = students).
It work's fine when I use echo $leerlingen within the foreach loop, but when I use the return statement it stops executing, because when return is used, it ends the function.
Code:
$leerlingen = array("tobias", "hasna", "aukje", "fred", "sep", "koen", "wahed", "anna", "jackie", "rashida", "winston", "sammy", "manon", "ben", "karim", "bart", "lisa", "lieke");
shuffle($leerlingen);
function maakGroepjes($leerlingen) {
$begin = 1;
foreach ($leerlingen as $leerling) {
if ($begin <= 2) {
echo $leerling;
$begin++;
}
}
}
echo maakGroepjes($leerlingen);
Can anyone tell me how to solve this problem?
You can return only one value inside a function, in this case is an array. I assume that the array have at least two values.
<?php
$leerlingen = array(
"tobias", "hasna", "aukje", "fred", "sep", "koen", "wahed", "anna", "jackie", "rashida", "winston", "sammy", "manon", "ben", "karim", "bart", "lisa", "lieke"
);
shuffle($leerlingen);
function maakGroepjes($leerlingen) {
//your result array
$result = array();
//Picking 2 random entries out of an array to $keys
$keys = array_rand($leerlingen, 2);
//Returning the array with two values
return array($leerlingen[$keys[0]], $leerlingen[$keys[1]]);
}
//assign the values to the vars
list($one, $two) = maakGroepjes($leerlingen);
//printing
echo $one . "<br>\n";
echo $two . "<br>\n";
?>
array_rand and other functions (rand) that rely on libc have a bad standard distribution. I'd always recommend using mt_rand() if you need it to be equally distributed, otherwise some entries will be heavily favored.
This is a good easy replacement for numerical arrays:
function array_mt_rand($array) {
return $array[ mt_rand( 0, count($array)-1 ) ];
}
$one = array_mt_rand($array);
$two = array_mt_rand($array);
You may need some extra checks if you have a small array and always want two distinct values though.
You could always try something like this.
function maakGroepjes($leerlingen) {
do {
$first_student = array_rand($leerlingen);
$second_student = array_rand($leerlingen);
} while ($leerlingen[$first_student] == $leerlingen[$second_student]);
return [$leerlingen[$first_studen], $leerlingen[$second_student]];
}
Which returns this.
Array
(
[0] => manon
[1] => winston
)
Also, the difference between a function printing/echo'ing information and returning information is pretty big.
You can't assign a variable to the echo statement inside of a function, whereas you could assign a variable to the return statement.
I would approach this a little differently.
function maakGroepjes($leerlingen) {
shuffle($leerlingen); // randomize the list of students
return array_chunk($leerlingen, 2); // break in into groups of two and return it
}
Then with
$groepjes = maakGroepjes($leerlingen);
you can generate all of the groups at once. No worries about repetition. This way if you need multiple groups, you can loop over the list of groups. If you really only need one group of two, then that will be
$groepjes[0];
which you can ouptut however you like. A very simple example:
foreach ($groepjes[0] as $student) echo "$student<br>";
Try this:
if ($begin <= 2) {
echo $leerling;
$begin++;
} else {
return
}
What this does is: every time through the loop, it looks at $begin. If it's less than or equal to two, it echoes that student and increments $begin. Otherwise, if it's greater than two, it returns, ending the function (and thus, the loop).
A perhaps better way to do it would be to just look at the ordinal directly:
foreach ($leerlingen as $ord => $leerling) {
echo $leerling;
if ($ord == 1) return;
}
Note the syntax in the loop definition. The "old =>" part sets the ordinal value as a variable as you loop through, letting you see which entry in the array you are currently on. So, this just loops through printing students. When it has printed the second student (remember, arrays are counted 0, 1, 2...) it returns.
Also, you probably don't want to echo maakGroepjes(). That function is what is echoing the student names. You probably don't want to echo the function result unless the function compiles the names into a string and returns the string or something.
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.
I have associative array such as:
$myArray = array(
'key1' => 'val 1',
'key2' => 'val 2'
...
);
I do not know the key values up front but want to start looping from the second element. In the example above, that would be from key2 onwards.
I tried
foreach(next(myArray) as $el) {
}
but that didnt work.
Alternatives may be array_slice but that seems messy. Am i missing something obvious?
There really is no "one true way" of doing this. So I'll take it as a benchmark as to where you should go.
All information is based on this array.
$array = array(
1 => 'First',
2 => 'Second',
3 => 'Third',
4 => 'Fourth',
5 => 'Fifth'
);
The array_slice() option. You said you thought this option was overkill, but it seems to me to be the shortest on code.
foreach (array_slice($array, 1) as $key => $val)
{
echo $key . ' ' . $val . PHP_EOL;
}
Doing this 1000 times takes 0.015888 seconds.
There is the array functions that handle the pointer, such as ...
current() - Return the current element in an array.
end() - Set the internal pointer of an array to its last element.
prev() - Rewind the internal array pointer.
reset() - Set the internal pointer of an array to its first element.
each() - Return the current key and value pair from an array and advance the array cursor.
Please note that the each() function has been deprecated as of PHP 7.2, and will be removed in PHP 8.
These functions give you the fastest solution possible, over 1000 iterations.
reset($array);
while (next($array) !== FALSE)
{
echo key($array) . ' ' . current($array) . PHP_EOL;
}
Doing this 1000 times, takes 0.014807 seconds.
Set a variable option.
$first = FALSE;
foreach ($array as $key => $val)
{
if ($first != TRUE)
{
$first = TRUE;
continue;
}
echo $key . ' ' . $val . PHP_EOL;
}
Doing this 1000 times takes 0.01635 seconds.
I rejected the array_shift options because it edits your array and you've never said that was acceptable.
This depends on whether you want to do this just once or many times, and on whether you still need the original array later on.
"First" pattern
$first = true;
foreach ($array as $key=>value) {
if($first) {
$first = false;
continue;
}
// ... more code ...
}
I personally use this solution quite often because it's really straight-forward, everybody gets this. Also, there is no performance hit of creating a new array and you can still operate on the original array after the loop.
However, if you have a couple of loops like this, it kind of starts looking a little unclean, because you need 5 extra lines of code per loop.
array_shift
array_shift($array);
foreach ($array as $key=>value) {
// .... more code ....
}
array_shift is a function tailored to this special case of not wanting the first element. Essentially it's a Perl-ish way of saying $array = array_slice($array, 1) which might not be completely obvious, especially since it modifies the original array.
So, you might want to make a copy of the original array and shift it, if you need both the shifted array multiple times and also the original array later on.
array_slice
And, of course, there is array_slice itself. I don't see anything wrong with array_slice if you want the original array to remain unchanged and you need the sliced array multiple times. However, if you're positive that you always want to slice just one element off, you might as well use the shorthand array_shift (and make a copy before if needed).
You can go with the obvious way:
$flag = false;
foreach($myArray as $el) {
if($flag) {
// do what you want
}
$flag = true;
}
Just another way of flexible iteration:
reset($myArray); // set array pointer to the first element
next($myArray); // skip first element
while (key($myArray) !== null) {
// do something with current($myArray)
next($myArray);
}
As far as I know foreach is just a kind of shortcut for this construction.
From Zend PHP 5 Certication study guide:
As you can see, using this set of functions [reset, next, key,
current, ...] requires quite a bit of work; to be fair, there are some
situations where they offer the only reasonable way of iterating
through an array, particularly if you need to skip back-and-forth
between its elements. If, however, all you need to do is iterate
through the entire array from start to finish, PHP provides a handy
shortcut in the form of the foreach() construct.
If your array was 0 based, it would be if($key>=1), but as your array starts at key 1, then this should work.
foreach ($array as $key=>$value){if($key>=2){
do stuff
}}
You could try:
$temp = array_shift($arr);
foreach($arr as $val) {
// do something
}
array_unshift($arr, $temp);
reset($myArray);
next($myArray);
while ($element = each($myArray))
{
//$element['key'] and $element['value'] can be used
}
My fairly simple solution when this issue pops up. It has the nice advantage of being easily being modified to be able to skip more than just the first element if you want it to.
$doomcounter = 0;
foreach ($doomsdayDevice as $timer){ if($doomcounter == 0){$doomcounter++; continue;}
// fun code goes here
}
I am still learning PHP and have a bit of an odd item that I haven't been able to find an answer to as of yet. I have a multidimensional array of ranges and I need to echo out the values for only the first & third set of ranges but not the second. I'm having a hard time just finding a way to echo out the range values themselves. Here is my code so far:
$array = array(
1=>range(1,4),
2=>range(1,4),
3=>range(1,4)
);
foreach(range(1,4) as $x)
{
echo $x;
}
Now I know that my foreach loop doesn't even reference my $array so that is issue #1 but I can't seem to find a way to reference the $array in the loop and have it iterate through the values. Then I need to figure out how to just do sets 1 & 3 from the $array. Any help would be appreciated!
Thanks.
Since you don't want to show the range on 2nd index, You could try
<?php
$array = array(
1=>range(1,4),
2=>range(1,4),
3=>range(1,4)
);
foreach($array as $i=>$range)
{
if($i!=2)
{
foreach($range as $value)
{
echo $value;
}
}
}
?>
Note: It's not really cool to name variables same as language objects. $array is not really an advisable name, but since you had it named that way, I didn't change it to avoid confusion
Do you want to do this?
foreach ($array as $item) {
echo $item;
}
You can use either print_r($array) or var_dump($array).
The second one is better because it structures the output, but if the array is big - it will not show all of it content. In this case use the first one - it will "echo" the whole array but in one row and the result is not easy readable.
Range is just an array of indexes, so it's up to you how to your want to represent it, you might want to print the first and the last index:
function print_range($range)
{
echo $range[0] . " .. " . $range[count($range) - 1] . "\n";
}
To pick the first and the third range, reference them explicitly:
print_range($array[1]);
print_range($array[3]);
here is one solution:
$array = array(
1=>range(1,4),
2=>range(1,4),
3=>range(1,4)
);
$i=0;
foreach($array as $y)
{ $i++;
echo "<br/>";
if($i!=0){ foreach($y as $x)
{
echo $x;
}
}
}
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