Getting value of nested array's which exist in every array - php

I have the following (nested) array:
array(3) { [16]=> array(3) { [0]=> int(159) [1]=> int(160) [2]=> int(158) }
[21]=> array(2) { [0]=> int(160) [1]=> int(158) }
[19]=> array(2) { [0]=> int(158) [1]=> int(159) } }
As you can see it contains 3 child array's. The child array's all contain the integer '158' as an value but also '159'. I want to somehow loop trough the child array's and do a check if all child array's contain that value. Then I want to return an array with only these values.
I know i could use array_intersect for this however the nested array's are generated dynamically so i'm not sure how to deal with this using array intersect:
<?php
$arr1 = array('158','250','342');
$arr2 = array('158','142','352');
$diff1 = array_intersect($arr1, $arr2);
print_r( $diff1 );
//RETURNS Array ( [0] => 158 )
?>

You can use the splat operator(...) to pass all the subarrays into array_intersect() in one go...
$arr1 = [['158','250','342'],['158','142','352'],['1421','158','3521']];
$diff1 = array_intersect(...$arr1);
print_r( $diff1 );
//RETURNS Array ( [0] => 158 )

After a bit searching around I found the following:
$result = call_user_func_array('array_intersect', $productStoreArray);
As seen on: php dynamic array_intersect
This solves my problem because it returns to me:
//RETURNS Array ( [0] => 158, 1 => 159 )

Related

PHP Associative Array in an Indexed Array

I have a $string:
'Name Height Weight
John 177 142
Jill 156 123
Jacob 183 157'
And I'm turning it into an $array of the following structure:
Array (
[0] => Array (
['Name'] => 'John'
['Height'] => '177'
['Weight'] => '142'
)
[1] = > Array (
['Name'] => 'Jill'
['Height'] => '156'
['Weight'] => '123'
)
[2] = > Array (
['Name'] => 'Jacob'
['Height'] => '183'
['Weight'] => '157'
)
)
Using the following code:
$rows = explode("\n",$string); //creates an indexed array of rows as strings
$headers = explode("\t",$rows[0]); //creates an indexed array of headers as strings
$rows = array_slice($rows,1); //removes headers from $rows
$array = Array();
foreach($rows as $row) {
$array[] = array_combine($headers, explode("\t",$row)); //creates associative arrays for each row
}
However, I cannot access the associative arrays inside of the indexed $array
For example, this doesn't work:
echo $array[0]['Name'];
Even though echo implode(', ', array_keys($array[0])); gives:
Name, Height, Weight
I've tried many different ways of accessing the associative arrays inside of the indexed array, but with no luck. What am I doing wrong?
EDIT:
So,
$string = "Name Height Weight
John 177 142
Jill 156 123
Jacob‌​ 183 157";
Does not work, but
$string = "Name\tHeight\tWeight\nJohn\t177\t142\nJill\t156\t123\nJacob‌​‌​\t183\t157";
does...
So I suppose the question is: What's the difference? And how would I interpret the former string as the latter?
Your code does not produce that array structure but it can be fixed like this:
$string = 'Name Height Weight
John 177 142
Jill 156 123
Jacob 183 157';
$rows = explode("\n",$string); //creates an indexed array of rows as strings
$headers = preg_split("#\s+#",trim($rows[0], "\n\r\t ")); //creates an indexed array of headers as strings, by splitting by any white space
var_dump($headers);
$rows = array_slice($rows,1); //removes headers from $rows
$array = Array();
foreach($rows as $row) {
$array[] = array_combine($headers, preg_split("#\s+#",trim($row, "\n\r\t "))); //creates associative arrays for each row, by splitting by any white space
}
var_dump($array);
This produces output:
array(3) {
[0]=>
string(4) "Name"
[1]=>
string(6) "Height"
[2]=>
string(6) "Weight"
}
array(3) {
[0]=>
array(3) {
["Name"]=>
string(4) "John"
["Height"]=>
string(3) "177"
["Weight"]=>
string(3) "142"
}
[1]=>
array(3) {
["Name"]=>
string(4) "Jill"
["Height"]=>
string(3) "156"
["Weight"]=>
string(3) "123"
}
[2]=>
array(3) {
["Name"]=>
string(5) "Jacob"
["Height"]=>
string(3) "183"
["Weight"]=>
string(3) "157"
}
}
The main ideas are that you must trim evey row string by any additional whitespaces and to split by the longest whitespace sequence.
//Use following code it will work as your answer
$string='Name Height Weight
John 177 142
Jill 156 123
Jacob 183 157';
$rows = explode("\n",$string); //creates an indexed array of rows as strings
$headers = explode("\t",$rows[0]); //creates an indexed array of headers as strings
$headers=array_filter(explode(" ",$headers[0])); ///t convert to space and filter remove empty element
$rows = array_slice($rows,1); //removes headers from $rows
$array = Array();
foreach($rows as $row) {
$row=explode("\t",$row);
$row=array_filter(explode(" ",$row[0]));
$array[] = array_combine($headers,$row); //creates associative arrays for each row
}
//print_r($array);
echo $array[0]['Name'];

Push columnar values of multiple arrays (of different lengths) to form a flat array

I have from 3 to 10 arrays containing 20 to 50 value each.
I want to merge them into a single, flat, indexed array, but not the way array_merge works.
I rather want to take the 1st value of the 1st array, then the 1st value of the second array, then the 1st value of the third array and so on.
Keys are not an issue here, It could be numerical or associative array, I'm just keeping the values, not the original keys.
Values in real application can be mixed so merging and sorting afterwards is not an option.
So if I had 3 arrays like so:
$array1 = array('1-1', '1-2', '1-3');
$array2 = array('2-1', '2-2', '2-3', '2-4');
$array3 = array('3-1', '3-2');
I would need the result to be an array containing the value in this order:
1-1, 2-1, 3-1, 1-2, 2-2, 3-2, 1-3, 2-3, 2-4
So far I have this piece of code :
$array = array($array1, $array2, $array3);
$newarray = array();
foreach ($array as $a) {
$v = array_shift($a);
if (isset($v)) {
$newarray[] = $v;
}
}
print_r($newarray);
but, of course, it only runs the 1st set of value and give me:
Array ( [0] => 1-1 [1] => 2-1 [2] => 3-1 )
array_shift is what I need here because it remove the value from the old array (I don't need it anymore) and I move it to the new array (if it isset). see: http://php.net/manual/en/function.array-shift.php
I'm pretty sure I will need a function and loop it until all arrays are empty, but I just can't wrap my head around this one. Any help will be greatly appreciated. Or even better if someone knows a native php function that does that.
Here's a simple one-liner...
$arr1 = ['1-1', '1-2', '1-3'];
$arr2 = ['2-1', '2-2', '2-3', '2-4'];
$arr3 = ['3-1', '3-2'];
$result = array_filter(call_user_func_array(array_merge, array_map(null, $arr1, $arr2, $arr3)));
So, maybe not so simple... Some explanation.
array_map(null, ...); makes use of the feature of array_map explained in example 4 of the PHP docs but without any transformation to the values (hence, null).
So, this will give you:
array(4) {
[0]=>
array(3) {
[0]=>
string(3) "1-1"
[1]=>
string(3) "2-1"
[2]=>
string(3) "3-1"
}
[1]=>
array(3) {
[0]=>
string(3) "1-2"
[1]=>
string(3) "2-2"
[2]=>
string(3) "3-2"
}
[2]=>
array(3) {
[0]=>
string(3) "1-3"
[1]=>
string(3) "2-3"
[2]=>
NULL
}
[3]=>
array(3) {
[0]=>
NULL
[1]=>
string(3) "2-4"
[2]=>
NULL
}
}
Then, we need to "flatten" the array, concatenating all the sub-arrays together.
This is achieved using array_merge, but that doesn't take an array, so we use call_user_func_array to feed the array into it's arguments.
Then the array_filter to remove the nulls (introduced by array_map due to the original arguments not being the same length).
Just added for reference, if you're running PHP 5.6+ you can take advantage of the new ... operator to signify n number of arguments in a function declaration and/or call. Implementation would be something like this (reference):
function merge_vertical(...$arrays) {
return array_filter(array_merge(...array_map(null, ...$arrays)));
}
print_r(merge_vertical($array1, $array2, $array3));
Output:
Array
(
[0] => 1-1
[1] => 2-1
[2] => 3-1
[3] => 1-2
[4] => 2-2
[5] => 3-2
[6] => 1-3
[7] => 2-3
[10] => 2-4
)
Try this code
$array1=array('1-1','1-2','1-3');
$array2=array('2-1','2-2','2-3','2-4');
$array3=array('3-1','3-2');
$array=array($array1,$array2,$array3);
$array2 = $array ;
function cmp($a, $b){
return (count($b) - count($a));
}
usort($array2, 'cmp');
$xax_length = count($array2[0]);
$newarray=array();
for($i=0;$i<$xax_length;$i++) {
foreach($array as &$a){
$v=array_shift($a);
if(isset($v)){
$newarray[]=$v;
}
}
}
print_r($newarray);
I would recommend hashing through all of the arrays in a for loop.
$array1=array('1-1','1-2','1-3');
$array2=array('2-1','2-2','2-3','2-4','2-5');
$array3=array('3-1','3-2');
$maxSize=max(count($array1),count($array2),count($array3));
$array=array($array1,$array2,$array3);
$newarray=array();
for ($i = 0; $i < $maxSize; $i++) {
for ($x = 0; $x < count($array); $x++) {
if(count($array[$x]) > $i){
$newarray[] = $array[$x][$i];
}
}
}
print_r($newarray);
While it is sexy to use array_map() to transpose array data so that columns of data can be easily extracted, the problem is that when processing data structures which are not perfectly shaped matrices, you will have null values generated.
Other answers fix the null population by calling array_filter() to mop up all of the unwanted nulls, but this will do harm to your result if you have false, null or zero-ish values in your data set that you actually wish to keep.
Also, this question states that key may be numeric or associative. This is another reason why transposing with array_map() is less attractive -- because it will choke on arrays with non-numeric keys.
While less elegant and sexy than some earlier posted answers, this answer wins out in terms of reliability because it will never destroy falsey values.
Add all arrays into a parent array (container), then iterate those arrays one at a time. "Shift" the first element off of each array and push it into the result array. If an array has no more elements, then unset() it so that it no longer occurs as a child of the parent array. (The original array variable will not be destroyed; only its copied version which exists inside the container.)
When the parent array has no more children, then stop looping.
Code: (Demo)
$array1 = [2 => 0, 0 => 1, 1 => '2'];
$array2 = [false, true, 'false' => false, 'true' => true];
$array3 = [null, 'null'];
$all = [$array1, $array2, $array3];
$result = [];
while ($all) {
foreach ($all as $index => &$array) {
$result[] = array_shift($array);
if (!$array) {
unset($all[$index]);
}
}
}
var_export($result);
Output:
array (
0 => 0,
1 => false,
2 => NULL,
3 => 1,
4 => true,
5 => 'null',
6 => '2',
7 => false,
8 => true,
)
You can use the + operator.
$c = $a + $b
Good luck !

How may I flatten this multiple arrays into 1?

This is the representation of my array from the view of var_dump and print_r :
I need to use array_unique but it doesn't work for this array so i was thinking that if i could flatten it to all fit one array then the unique will work.
var_dump :
{
["Source"]=>
string(12) "10.96.250.49"
}
array(1) {
["Source"]=>
string(12) "10.96.250.49"
}
array(1) {
["Source"]=>
string(12) "10.96.250.49"
}
print_r :
Array
(
[Source] => 10.96.250.49
)
Array
(
[Source] => 10.96.250.49
)
Array
(
[Source] => 10.96.250.49
)
If you're using PHP 5.5+, you can use array_column() to extract all the Source values:
$result = array_unique(array_column($array, 'Source'));
If you're using an older PHP version, simply loop through your array and create a flattened array, like so:
$new = array();
foreach ($array as $subarr) {
$new[] = $subarr['Source'];
}
$result = array_unique($new);

How many i remove duplicates from this Array? [duplicate]

This question already has answers here:
How to remove duplicate values from a multi-dimensional array in PHP
(18 answers)
How to remove duplicate values from an array in PHP
(27 answers)
Closed 9 years ago.
First i will like to say that, i have looked into other post but failed trying to accomplish my needs. I have used array_unique($array) but the duplicates don't get discarded. This is a view of my array using var_dump:
{
[0]=>
string(12) "44.94.192.40"
}
array(1) {
[0]=>
string(12) "44.94.192.41"
}
array(1) {
[0]=>
string(9) "44.94.1.1"
}
array(1) {
[0]=>
string(9) "44.94.1.1"
}
array(1) {
[0]=>
string(13) "44.96.253.100"
}
"44.94.1.1" is a duplicate which i hope to remove but i can't. Does this have to do with my array structure ?
Edited in response to your comment:
From the documentation on array_unique():
Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same.
So the fact that each of your values is an array is interfering.
Try creating an array containing just the string values:
$new_array = array();
foreach ($array as $value) {
$new_array[] = $value[0];
}
$new_array = array_unique($new_array);
You can flatten your array and do array unique or do array_map with a reference to a foreign array
<?php
$data = array(
array("44.94.192.40"),
array("44.94.192.41"),
array("44.94.1.1"),
array("44.94.1.1"),
array("44.96.253.100"),
);
$visited = array();
array_map(function($v) use ( &$visited ){
if(array_search( $v[0], $visited ) === false){
$visited[] = $v[0];
};
},$data);
var_dump($visited);
array(4) {
[0]=>
string(12) "44.94.192.40"
[1]=>
string(12) "44.94.192.41"
[2]=>
string(9) "44.94.1.1"
[3]=>
string(13) "44.96.253.100"
}
You can find a variety of ways to remove duplicates from a multidimensional array on the php doc page of array_unique in the user comments
http://us3.php.net/array_unique
Orel also mentioned a duplicate question that at a glance also contains a function for doing the same
How to remove duplicate values from an array in PHP
For simplicity I have picked one for you, but depending on exactly what you want, there are many different flavors on the php page I linked
foreach ($arrAddressList AS $key => $arrAddress) {
$arrAddressList[$key] = serialize($arrAddress);
}
$arrAddressList = array_unique($arrAdressList);
foreach ($arrAddressList AS $key => $strAddress) {
$arrAddressList[$key] = unserialize($strAddress);
}
You can do it with a foreach loop
$array = array(
array("44.94.192.40"),
array("44.94.192.41"),
array("44.94.1.1"),
array("44.94.1.1"),
array("44.96.253.100"),
);
$temp_arr=array();
foreach($array as $elementKey => $element)
{
foreach($element as $valueKey => $value)
{
if(in_array($value,$temp_arr)) unset($array[$elementKey]);
else $temp_arr[]=$value;
}
}
print_r($array);
Output would be:
Array ( [0] => Array ( [0] => 44.94.192.40 ) [1] => Array ( [0] => 44.94.192.41 ) [2] => Array ( [0] => 44.94.1.1 ) [4] => Array ( [0] => 44.96.253.100 ) )

What's the difference between array_merge and array + array? [duplicate]

This question already has answers here:
Merging two arrays with the "+" (array union operator) How does it work?
(9 answers)
Closed last year.
A fairly simple question. What's the difference between:
$merged = array_merge($array1, $array2);
and
$merged = $array1 + $array2;
?
Here's a simple illustrative test:
$ar1 = [
0 => '1-0',
'a' => '1-a',
'b' => '1-b'
];
$ar2 = [
0 => '2-0',
1 => '2-1',
'b' => '2-b',
'c' => '2-c'
];
print_r($ar1+$ar2);
print_r(array_merge($ar1,$ar2));
with the result:
Array
(
[0] => 1-0
[a] => 1-a
[b] => 1-b
[1] => 2-1
[c] => 2-c
)
Array
(
[0] => 1-0
[a] => 1-a
[b] => 2-b
[1] => 2-0
[2] => 2-1
[c] => 2-c
)
Notice that duplicate non-numeric keys will take the first value using the union operator but the later one using the array_merge.
For numeric keys, the first value will be used with the union operator whereas the all the values will be used with the array_merge, just reindexed.
I generally use union operator for associative arrays and array_merge for numeric. Of course, you can just as well use the array_merge for associative, just that the later values overwrite earlier ones.
The difference is:
The + operator takes the union of the two arrays, whereas the array_merge function takes the union BUT the duplicate keys are overwritten.
Source: https://softonsofa.com/php-array_merge-vs-array_replace-vs-plus-aka-union/
Stop using array_merge($defaults, $options):
function foo(array $options)
{
$options += ['foo' => 'bar'];
// ...
}
Note: array_replace function exists since PHP5.3.
array_merge() causes all numeric keys found in the input arrays to be reindexed in the resultant array. The union operator + does not cause a reindex.
The + sign only takes the value from the first occurence of an array key.
array_merge takes the value from the last occurrence of an array key.
Example:
$first = ['a'=>'one',
'b'=>'two',
'c'=>'three'];
$second = ['a'=>'fourth',
'b'=>'fifth',
'c'=>'sixth',
'3'=>'number three'];
$merged = $first + $second;
echo "<pre> plus sign merge\n";
var_dump($merged);
$merged = array_merge($first,$second);
echo "\n array_merge function merge\n";
var_dump($merged);
This outputs:
plus sign merge
array(4) {
["a"]=>
string(3) "one"
["b"]=>
string(3) "two"
["c"]=>
string(5) "three"
[3]=>
string(12) "number three"
}
array_merge function merge
array(4) {
["a"]=>
string(6) "fourth"
["b"]=>
string(5) "fifth"
["c"]=>
string(5) "sixth"
[0]=>
string(12) "number three"
}
Interesting to note in this is that the array_merge actally erases the '3' index of number three even though it's a string, because it's a number.
So take care when merging with array_merge arrays with numerical indexes. They might lose their keys. if they are important to you precede them with a string.
Instead of '3' => 'three' use something like '_3' => 'three'
Also if you use numerical indexes it's important to note that if you add two array, it only looks at the numerical index and takes the value from the "first" array that has an array key with that value.
Array merge will merge the arrays together, ignoring similar keys and values.
So depending on the "type" of array indexes, numerical or string, the results will vary.
$arr = ['foo', 'bar', 'baz'];
$arr2 = ['xfoo', 'xbar', 'baz'];
$arr3 = $arr2 + $arr;
$arr4 = array_merge($arr, $arr2);
var_dump($arr3);
which gives the output:
array(3) {
[0]=>
string(4) "xfoo"
[1]=>
string(4) "xbar"
[2]=>
string(3) "baz"
}
array(6) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
[2]=>
string(3) "baz"
[3]=>
string(4) "xfoo"
[4]=>
string(4) "xbar"
[5]=>
string(3) "baz"
}
var_dump($arr4);
I believe array_merge overwrites duplicate non_numeric keys while $array1 + $array2 does not.
Yet another example (arrays without explicit keys; it's obvious regarding to how the operator + and array_merge work, but "obvious" things are simpler when seen ;))
$a = array('apple');
$b = array('orange', 'lemon');
echo '$a + $b = '; print_r($a + $b);
echo 'array_merge($a, $b) = '; print_r(array_merge($a, $b));
will give:
$a + $b = Array
(
[0] => apple
[1] => lemon
)
array_merge($a, $b) = Array
(
[0] => apple
[1] => orange
[2] => lemon
)
Please pay attention for another difference: the union (+) won't overwrite non-empty value with empty value (considering a same key), whereas array_merge will:
$a = array('foo' => 'bar');
$b = array('foo' => ''); // or false or 0
print_r($a+$b);
print_r(array_merge($a, $b);
Outputs :
Array
(
[foo] => bar
)
Array
(
[foo] => 0
)
So apparently if you change the order both union and merge will do the same thing
$a = array('foo' => 'bar', 'x' => 'fromA');
$b = array('foo' => null, 'x' => 'fromB');
echo '$a+$b: ';
var_dump($a+$b);
echo '$b+$a: ';
var_dump($b+$a);
echo 'array_merge($a, $b): ';
var_dump(array_merge($a, $b));
echo 'array_merge($b, $a): ';
var_dump(array_merge($b, $a));
Outputs :
$a+$b: array(2) {
["foo"]=>
string(3) "bar"
["x"]=>
string(5) "fromA"
}
$b+$a: array(2) {
["foo"]=>
NULL
["x"]=>
string(5) "fromB"
}
array_merge($a, $b): array(2) {
["foo"]=>
NULL
["x"]=>
string(5) "fromB"
}
array_merge($b, $a): array(2) {
["foo"]=>
string(3) "bar"
["x"]=>
string(5) "fromA"
}
Keep in mind the order of the arrays.

Categories