Multiple values in array excluding specified key [duplicate] - php

This question already has answers here:
Deleting an element from an array in PHP
(25 answers)
Closed 9 months ago.
I'm trying to verify if certain values exist within an array excluding a specific key:
$haystack = array(
"id" => 1,
"char1" => 2,
"char2" => 3,
"char3" => 4,
);
$needles = array(2, 4);
Solution that I found here: in_array multiple values
function in_array_all($needles, $haystack) {
return empty(array_diff($needles, $haystack));
}
The problem is that I'm checking if certain chars exist within the array. This will work fine in this case:
$exists = in_array_all([2, 4], $haystack); // true
But it'll cause an issue in this situation:
$exists = in_array_all([1, 3], $haystack); // true
It found the value 1 in the key id and therefor evaluates as true while a char with id 1 is not within the array. How can I make it so that it excludes the key id within the search?
Note: This is example data. The real data is much larger, so just using if / else statements isn't really viable.

function in_array_all($needles, $haystack) {
return empty(array_diff($needles, $haystack));
}
function excludeKeys($haystack){
$tempArray = array();
foreach($haystack as $key => $value){
if ($key == "id"){
// Don't include
}else{
$tempArray[$key] = $value;
}
}
return $tempArray;
}
$haystack = array(
"id" => 1,
"char1" => 2,
"char2" => 3,
"char3" => 4,
);
$exists = in_array_all([1, 3], excludeKeys($haystack));
echo("Exists: ".($exists ? "Yes" : "No"));
This basically just returns the array without the keys you specify. This keeps the original array in tact for later use.
Edit:
These bad solutions are really a symptom of a problem in your data structure. You should consider converting your array to an object. It looks like this:
$object = new stdClass();
$object->id = 1;
$object->chars = array(2, 3, 4);
$exists = in_array_all([1, 3], $object->chars);
This is how you're supposed to separate your data up. This way you can properly store your information by key. Furthermore you can store other objects or arrays within the object specific to a key, as shown above.

Unset id index and then do search:
function in_array_any($needles, $haystack) {
unset($haystack['id']);
return !array_diff($needles, $haystack);
}
https://3v4l.org/PTjOS

Related

How to check equality of two arrays when the key_names are different in laravel

I am a beginner to laravel yet please help me to figure this out.I'm creating a question/answer app these days. The application have some multi choice mcq questions aswell. Inorder to match those multi choice mcq answers with correct answers, I need to match two arrays and get results.
Ex:-
array1 = [{"id":15},{"id":16}]
array2 = [{"answer_option_id":15},{"answer_option_id":17}]
Note : array1 includes the correct options (correct answer). array2 includes the options given by user.array2 can have any length.Because in multi choice question, we can select any number of answer options.
But, to know if the user have given the correct options, I need to match array2 with array1 and they must be equal.
I tried some built_in functions such as array_intersect() but it didn't work.
By using Laravel Collection :
$array1 = [["id"=>15],["id"=>16],];
$array2 = [["answer_option_id"=>16],["answer_option_id"=>15]];
$array_1 = collect($array1)->pluck('id')->sort()->values()->all();
$array_2 = collect($array2)->pluck('answer_option_id')->sort()->values()->all();
if($array_1 == $array_2){
echo "correct";
}else{
echo "incorrect";
}
You must have Valid PHP Arrays
$array2 = [["answer_option_id" => 15], ["answer_option_id" => 17]];
$answerOptionsIds = [];
foreach($array2 as $value) {
$answerOptionsIds[] = $value['answer_option_id'];
}
// $answerOptionsIds => [15, 17]
// OR you can make use of Illuminate\Support\Arr::flatten() helper
// $answerOptionsIds = Illuminate\Support\Arr::flatten($array2);
$array1 = [["id" => 15], ["id" => 16]];
$correctAnswersIds = [];
foreach($array1 as $value) {
$correctAnswersIds[] = $value['id'];
}
// $correctAnswersIds => [15, 16]
// OR
// $correctAnswersIds = Illuminate\Support\Arr::flatten($array1);
$match = true;
foreach($correctAnswersIds as $correctAnswer) {
if (!in_array($correctAnswer, $answerOptionsIds)) {
$match = false;
break;
}
}

How to allow same keys in one array? [duplicate]

This question already has answers here:
PHP Associative Array Duplicate Keys
(6 answers)
Closed 4 years ago.
I need to add the same keys to the array, but with different values,
foreach ($selections as $selection) {
$array += [$selection['option_id']=>$selection['product_id']];
}
// example output
$array = [30=>12,14=>10],
but really it should be
[30=>7,30=>12,14=>10];
When the key repeats, it merges.
You just can't.
But you can make the value of this key an array.
So you'll have
$array = [30=>[7,12],14=>10];
You can use any array functions on $array[30]
What you should do is to return the products ids as an array:
$array = array_reduce($selections, function ($carry, $selection) {
if (!isset($carry[$selection['option_id']])) {
$carry[$selection['option_id']] = [];
}
$carry[$selection['option_id']][] = $selection['product_id'];
return $carry;
}, []);
Now the result would be:
[30 => [7, 12], 14 => [10]];
Keys in array are, as the word itself says, keys to access the value they contain and each key must be unique, else you won't have a way to . If you could have two time or more the same value, how could you tell which will access one value and which one will access the other one? To solve your problem you have a way: generate a multidimensional array such that you can have multiple value stored "behind" a single key. E.g. [30 => [7,12], 14 => 10]
Based on your code you can just create a double loop with a nested foreach to navigate through all the value, something like:
foreach ($selections as $selection) {
if(!is_array($selection['product_id']) $array += [$selection['option_id']=>$selection['product_id']];
else {
foreach ($selection['product_id'] as $product) {
$array += [$selection['option_id']=> product];
}
}
}

PHP merge (single depth) recursive based on first index (date)

I have searched alot, but can't find the exact similair question. The built-in function in PHP don't do what I'm looking for. Note: array_merge_recursively(...) came close, but didn't keep the indexes.
I have for example to arrays in PHP (json visualization):
[
["1-6-13", 10],
["30-6-13", 13],
["20-9-13", 28]
]
and:
[
["18-2-13", 7],
["30-6-13", 9]
]
And I want to merge those two, based on their date. However not every date matches the other one, it is important that the value of array 1 will be on index 1, and the value of array 2 must be appended to index 2. The values which don't exists must be for instance null.
So the desired result would look like:
[
["18-2-13", null, 7],
["1-6-13", 10, null],
["30-6-13", 13, 9],
["20-9-13", 28, null]
]
I hope someone can help me out!
You can first get a collection of all dates like this:
$dates = array_merge(array_map('reset', $data1), array_map('reset', $data2));
This collection includes duplicates, but we don't really care (we could remove them with array_unique if that was a problem).
Side note: if running PHP >= 5.5 it would be preferable to do array_column($arr, 0) instead of array_map('reset', $arr).
Then project that into an array of arrays, using the dates as keys:
$result = array_fill_keys($dates, array(null, null, null));
And fill it up with data:
foreach($data1 as $pair) {
list($date, $num) = $pair;
$result[$date][0] = $date;
$result[$date][1] = $num;
}
foreach($data2 as $pair) {
list($date, $num) = $pair;
$result[$date][0] = $date;
$result[$date][2] = $num;
}
Of course the above can easily be generalized for an arbitrary number of arrays with a loop.
Finally, if you want the $result to be numerically indexed then lose the dates that were used as keys:
$result = array_values($result);
See it in action.
You could do this. The benefit is that you only loop through the arrays once:
$dates = array();
foreach( $array1 as $val ) {
$dates[$val[0]] = array( $val[0], $val[1], null );
}
foreach( $array2 as $val) {
$dates[$val[0]][0] = $val[0];
$dates[$val[0]][1] = isset( $dates[$val[0]][1] ) ? $dates[$val[0]][1] : null;
$dates[$val[0]][2] = $val[1];
}

PHP - Get array value with a numeric index

I have an array like:
$array = array('foo' => 'bar', 33 => 'bin', 'lorem' => 'ipsum');
echo native_function($array, 0); // bar
echo native_function($array, 1); // bin
echo native_function($array, 2); // ipsum
So, this native function would return a value based on a numeric index (second arg), ignoring assoc keys, looking for the real position in array.
Are there any native function to do that in PHP or should I write it?
Thanks
$array = array('foo' => 'bar', 33 => 'bin', 'lorem' => 'ipsum');
$array = array_values($array);
echo $array[0]; //bar
echo $array[1]; //bin
echo $array[2]; //ipsum
array_values() will do pretty much what you want:
$numeric_indexed_array = array_values($your_array);
// $numeric_indexed_array = array('bar', 'bin', 'ipsum');
print($numeric_indexed_array[0]); // bar
I am proposing my idea about it against any disadvantages array_values( ) function, because I think that is not a direct get function.
In this way it have to create a copy of the values numerically indexed array and then access. If PHP does not hide a method that automatically translates an integer in the position of the desired element, maybe a slightly better solution might consist of a function that runs the array with a counter until it leads to the desired position, then return the element reached.
So the work would be optimized for very large array of sizes, since the algorithm would be best performing indices for small, stopping immediately. In the solution highlighted of array_values( ), however, it has to do with a cycle flowing through the whole array, even if, for e.g., I have to access $ array [1].
function array_get_by_index($index, $array) {
$i=0;
foreach ($array as $value) {
if($i==$index) {
return $value;
}
$i++;
}
// may be $index exceedes size of $array. In this case NULL is returned.
return NULL;
}
Yes, for scalar values, a combination of implode and array_slice will do:
$bar = implode(array_slice($array, 0, 1));
$bin = implode(array_slice($array, 1, 1));
$ipsum = implode(array_slice($array, 2, 1));
Or mix it up with array_values and list (thanks #nikic) so that it works with all types of values:
list($bar) = array_values(array_slice($array, 0, 1));

How to search Array for multiple values in PHP?

I need to get the keys from values that are duplicates. I tried to use array_search and that worked fine, BUT I only got the first value as a hit.
I need to get both keys from the duplicate values, in this case 0 and 2. The search result output as an array would be good.
Is there a PHP function to do this or do I need to write some multiple loops to do it?
$list[0][0] = "2009-09-09";
$list[0][1] = "2009-05-05";
$list[0][2] = "2009-09-09";
$list[1][0] = "first-paid";
$list[1][1] = "1";
$list[1][2] = "last-unpaid";
echo array_search("2009-09-09",$list[0]);
You want array_keys with the search value
array_keys($list[0], "2009-09-09");
which will return an array of the keys with the specified value, in your case [0, 2]. If you want to find the duplicates as well, you can first make a pass with array_unique, then iterate over that array using array_keys on the original; anything which returns an array of length > 1 is a duplicate, and the result is the keys in which the duplicates are stored. Something like...
$uniqueKeys = array_unique($list[0])
foreach ($uniqueKeys as $uniqueKey)
{
$v = array_keys($list[0], $uniqueKey);
if (count($v) > 1)
{
foreach ($v as $key)
{
// Work with $list[0][$key]
}
}
}
In array_search() we can read:
If needle is found in haystack more
than once, the first matching key is
returned. To return the keys for all
matching values, use array_keys() with
the optional search_value parameter
instead.
The following combination of function calls will give you all duplicate values:
$a = array(1, 1, 2, 3, 4, 5, 99, 2, 5, 2);
$unique = array_unique($a); // preserves keys
$diffkeys = array_diff_key($a, $unique);
$duplicates = array_unique($diffkeys);
echo 'Duplicates: ' . join(' ', $duplicates) . "\n"; // 1 2 5
You can achieve that using array_search() by using while loop and the following workaround:
while (($key = array_search("2009-09-09", $list[0])) !== FALSE) {
print($key);
unset($list[0][$key]);
}
Source: cue at openxbox at php.net
For one-multidimensional array, you may use the following function to achieve that (as alternative to array_keys()):
function array_isearch($str, $array){
$found = array();
foreach ($array as $k => $v) {
if (strtolower($v) == strtolower($str)) {
$found[] = $k;
}
}
return $found;
}
Source: robertark, php.net
The PHP manual states in the Return Value section of the array_search() function documentation that you can use array_keys() to accomplish this. You just need to provide the second parameter:
$keys = array_keys($list[0], "2009-09-09");
$userdb=Array
(
(0) => Array
(
(uid) => '100',
(name) => 'Sandra Shush',
(url) => 'urlof100'
),
);
$key = array_search(100, array_column($userdb, 'uid'));

Categories