PHP Extract and count first elements of each element in multidimensional array - php

I have this array in php,
$mainArray = array(
array("apple","two", "grren"),
array("samsung","five", "red"),
array("microsoft","one","gray"),
array("apple","nine", "blue"),
array("samsung","ten", "white"),
array("nokia","seven", "yellow")
);
I can easily loop through it and extract all the first entries of each array like this:
foreach($mainArray as $w => $n) {
$whatever = $mainArray[$w][0];
}
I'm trying to count how many entries are the same in the first element of each array, and have a result of something like:
apple (2)
samsung (2)
microsoft (1)
nokia (1)
I'm just not sure what is the correct way to do this.
Thank you in advance.

print_r(
array_count_values(
array_map('array_shift', $mainArray)
)
);
Output (Demo):
Array
(
[apple] => 2
[samsung] => 2
[microsoft] => 1
[nokia] => 1
)
So even I am a big fan of foreach, why did I not use it here?
First of all, to count values in an array, in PHP we have array_count_values. It does the job for us.
So the only problem left was to get all the first items into an array to count them with array_count_values. That is a typical mapping job, and I like mapping, too, next to foreach so I tried if array_map together with array_shift worked - and it did.
However you might want to look for a function called array_column. It's not yet available with PHP itself, but as PHP code in another answer:
$counts = array_count_values(array_column($mainArray, 0));

$count = array();
foreach($mainArray as $array) {
$first = $array[0];
if(!isset($count[$first])) $count[$first] = 0;
$count[$first]++;
}
print_r($count);

Collect every first element of the deep arrays by pushing them into a new array ($result in my example) and then call array_count_values() on that array. Like so:
$mainArray = array(
array("apple","two", "grren"),
array("samsung","five", "red"),
array("microsoft","one","gray"),
array("apple","nine", "blue"),
array("samsung","ten", "white"),
array("nokia","seven", "yellow")
);
$result = array();
foreach( $mainArray as $k => $v )
{
// let's continue if $v is not an array or is empty
if( !is_array( $v ) || empty( $v ) ) continue;
$result[] = $v[ 0 ];
}
var_dump( array_count_values( $result ) );

You can loop through the $mainArray to build a full array/list of values and then use array_count_values() on that:
$firstElements = array();
foreach ($mainArray as $arr) {
$firstElements[] = $arr[0];
}
$counts = array_count_values($firstElements);
Another option would be to loop through $mainArray and insert the value as an index for an array (if it doesn't already exist) and then increment it each time (this will do the same thing as array_count_values() in the end):
$counts = array();
foreach ($mainArray as $arr) {
if (!isset($counts[$arr[0]])) $counts[$arr[0]] = 0;
$counts[$arr[0]]++;
}

You can do it just like this:
foreach($mainArray as $n) {
$count[$n[0]] = isset($count[$n[0]]) ? $count[$n[0]]++ : 1;
}
var_dump($count); //should give you something like
/*
array(4) {
["apple"]=>
int(2)
["samsung"]=>
int(2)
["microsoft"]=>
int(1)
["nokia"]=>
int(1)
}
*/

Related

PHP get ranges of same values from array

Is there any way to get the key range of same values and make a new array?
Let's say we have an Array Like this in php :
$first_array = ['1'=>'a','2'=>'a','3'=>'a','4'=>'b','5'=>'b','6'=>'a','7'=>'a'];
How can i get this array? Is there any function for this?
$second_array = ['1-3'=>'a','4-5'=>'b','6-7'=>'a'];
Loop through it, extract the keys, generate the ranges and insert to the new array -
$first_array = ['1'=>'a','2'=>'a','3'=>'a','4'=>'b','5'=>'b'];
$flip = array();
foreach($first_array as $key => $val) {
$flip[$val][] = $key;
}
$second_array = [];
foreach($flip as $key => $value) {
$newKey = array_shift($value).' - '.end($value);
$second_array[$newKey] = $key;
}
Output
array(2) {
["1 - 3"]=>
string(1) "a"
["4 - 5"]=>
string(1) "b"
}
regarding your first question you can get range of each value using foreach() loop.
$first_array = ['1'=>'a','2'=>'a','3'=>'a','4'=>'b','5'=>'b'];
foreach($first_array as $key=>$value)
{
//do your coding here, $key is the index of the array and $value is the value at that range, you can use that index and value to perform array manipulations
}
Regarding your second question it not exactly clear what are trying to implement there. But what ever you want to do like creating a new array with modified index and other things can be done within this foreach() loop itself
I hope this helps you.
If someone is still looking for an answer, here is what I did.
Given the array
$first_array = ['0'=>'a',
'1'=>'a',
'2'=>'a',
'3'=>'a',
'4'=>'a',
'5'=>'b',
'6'=>'b',
'7'=>'a',
'8'=>'a']
I build a multidimensional array, in which each element is an array of three more elements:
[0] - The value in the first array
[1] - The key where the value starts repeating
[2] - The last key where the value stops repeating
The code
$arrayRange = [];
for($i = 0; $i < count($first_array); $i++){
if(count($arrayRange) == 0){
// The multidimensional array is still empty
$arrayRange[0] = array($first_array[$i], $i, $i);
}else{
if($first_array[$i] == $arrayRange[count($arrayRange)-1][0]){
// It's still the same value, I update the value of the last key
$arrayRange[count($arrayRange)-1][2] = $i;
}else{
// It's a new value, I insert a new array
$arrayRange[count($arrayRange)] = array($first_array[$i], $i, $i);
}
}
}
This way you get a multidimensional array like this:
$arrayRange[0] = array['a', 0, 4];
$arrayRange[1] = array['b', 5, 6];
$arrayRange[2] = array['a', 7, 8];

Find out which items were added and removed in an array

I'm building application that tells user which are old and which are new bank notes when I increase sum with X. Everything is fine, but I'm wondering how I can now get list of added and removed items of array?
$old = array(1,5,10);
$new = array(1,5,1);
$added = array_diff($new,$old);
$removed = array_diff($old,$new);
And this is what code above returns:
$added is array(). Incorrect, it should be array([2] => 1).
$removed is array([2] => 10). Correct.
What am I doing wrong, and how can I fix it?
$added = array_diff($new,$old);
In the above statement, array_diff() compares $new with $old and returns the values in $new that are not present in $old. There is no such value, and hence it returns an empty array.
In short, array_diff() doesn't work with duplicate values. You will have to write a custom function to achieve this. Here's an example:
function array_diff_once($array1, $array2) {
foreach($array2 as $val) {
if (false !== ($pos = array_search($val, $array1))) {
unset($array1[$pos]);
}
}
return $array1;
}
You can simply use it the same way you did before:
$added = array_diff_once($new,$old);
$removed = array_diff_once($old,$new);
print_r() of these arrays would correctly output:
Array
(
[2] => 1
)
Array
(
[2] => 10
)
Working demo
If you want to check the keys in addition to the values of an array, you should use array_diff_assoc() instead of array_diff():
<?php
$old = array(1,5,10);
$new = array(1,5,1);
$added = array_diff_assoc($new,$old);
$removed = array_diff_assoc($old,$new);
echo "<pre>\n"; \\ prints array(1) { [2]=> int(1) }
var_dump($added);
var_dump($removed);
echo "</pre>\n";
?>

PHP: Delete values from nested arrays

I am extracting duplicated values from nested arrays. I would like to delete these extraceted items from the $bigarray. would you give me some ideas...?
$bigarray = array(
"430" => array('milk', 'turky', 'apple'),
"433" => array('milk', 'apple', 'orange', 'england'),
"444" => array('milk', 'apple', 'orange', 'spain')
);
$intersected = null;
foreach ($bigarray as $arr) {
$intersected = $intersected ? array_intersect($arr, $intersected) : $arr;
if (!$intersected) {
break; // no reason to continue
}
}
foreach ($intersected as $inter){
foreach ($bigarray as $arr) {
foreach ($arr as $value=>$key) {
if ($key == $inter){
unset($arr[$value]);
}
}
//print_r($arr);
}
}
print_r($bigarray );
You should look at array_merge as it will merge 2 arrays together and only keep one duplicate. From the manual:
If the input arrays have the same string keys, then the later value
for that key will overwrite the previous one. If, however, the arrays
contain numeric keys, the later value will not overwrite the original
value, but will be appended.
Sounds like homework and the question isn't very clear so that is all I can provide for now.
Is this what you're looking for?
foreach($bigarray as $id => $arr)
$bigarray[$id] = array_unique($arr);
I don't completely understood your question, but using array_unique() in your array I've got the following output:
array(1) {
[430]=>
array(3) {
[0]=>
string(4) "milk"
[1]=>
string(5) "turky"
[2]=>
string(5) "Apple"
}
}
Maybe this could be a way of acchieving what you want.
function array_unique_nested($arr=array(),$matched=array(),$cm=false){
foreach($arr as $i=>$v){
if (is_array($v)) {$arr[$i]=array_unique_nested($v,$matched,false);
$matched=array_unique_nested($v,$matched,true); continue;}
if (in_array($v,$matched)) {unset($arr[$i]);continue;}
$matched[]=$v;}
if ($cm) return $matched;
else return $arr;}
In case that doesn't work, this code snippet from http://php.net/manual/en/function.array-unique.php should do the trick.
if( !function_exists( 'array_flat' ) )
{
function array_flat( $a, $s = array( ), $l = 0 )
{
# check if this is an array
if( !is_array( $a ) ) return $s;
# go through the array values
foreach( $a as $k => $v )
{
# check if the contained values are arrays
if( !is_array( $v ) )
{
# store the value
$s[ ] = $v;
# move to the next node
continue;
}
# increment depth level
$l++;
# replace the content of stored values
$s = array_flat( $v, $s, $l );
# decrement depth level
$l--;
}
# get only unique values
if( $l == 0 ) $s = array_values( array_unique( $s ) );
# return stored values
return $s;
} # end of function array_flat( ...
}
You can use the array_unique($array,[, int $sort_flags] function. if you don't specify the optional sort_flag, the function will compare values converting everything to string. if you have values other than string in the array, you can specify sort_flag to be one of the following values
SORT_REGULAR - compare items normally (don't change types)
SORT_NUMERIC - compare items numerically
SORT_STRING - compare items as strings
SORT_LOCALE_STRING - compare items as strings, based on the current locale.
Example from PHP.net
$input = array("a" => "green", "red", "b" => "green", "blue", "red");
$result = array_unique($input);
print_r($result);
for more information refer
http://php.net/manual/en/function.array-unique.php

PHP merge array(s) and delete double values

WP outputs an array:
$therapie = get_post_meta($post->ID, 'Therapieen', false);
print_r($therapie);
//the output of print_r
Array ( [0] => Massagetherapie )
Array ( [0] => Hot stone )
Array ( [0] => Massagetherapie )
How would I merge these arrays to one and delete all the exact double names?
Resulting in something like this:
theArray
(
[0] => Massagetherapie
[1] => Hot stone
)
[SOLVED] the problem was if you do this in a while loop it wont work here my solution, ty for all reply's and good code.: Its run the loop and pushes every outcome in a array.
<?php query_posts('post_type=therapeut');
$therapeAr = array(); ?>
<?php while (have_posts()) : the_post(); ?>
<?php $therapie = get_post_meta($post->ID, 'Therapieen', true);
if (strpos($therapie,',') !== false) { //check for , if so make array
$arr = explode(',', $therapie);
array_push($therapeAr, $arr);
} else {
array_push($therapeAr, $therapie);
} ?>
<?php endwhile; ?>
<?php
function array_values_recursive($ary) { //2 to 1 dim array
$lst = array();
foreach( array_keys($ary) as $k ) {
$v = $ary[$k];
if (is_scalar($v)) {
$lst[] = $v;
} elseif (is_array($v)) {
$lst = array_merge($lst,array_values_recursive($v));
}}
return $lst;
}
function trim_value(&$value) //trims whitespace begin&end array
{
$value = trim($value);
}
$therapeAr = array_values_recursive($therapeAr);
array_walk($therapeAr, 'trim_value');
$therapeAr = array_unique($therapeAr);
foreach($therapeAr as $thera) {
echo '<li><input type="checkbox" value="'.$thera.'">'.$thera.'</input></li>';
} ?>
The following should do the trick.
$flattened = array_unique(call_user_func_array('array_merge', $therapie));
or the more efficient alternative (thanks to erisco's comment):
$flattened = array_keys(array_flip(
call_user_func_array('array_merge', $therapie)
));
If $therapie's keys are strings you can drop array_unique.
Alternatively, if you want to avoid call_user_func_array, you can look into the various different ways of flattening a multi-dimensional array. Here are a few (one, two) good questions already on SO detailing several different methods on doing so.
I should also note that this will only work if $therapie is only ever a 2 dimensional array unless you don't want to flatten it completely. If $therapie is more than 2 dimensions and you want to flatten it into 1 dimension, take a look at the questions I linked above.
Relevant doc entries:
array_flip
array_keys
array_merge
array_unique
call_user_func_array
It sounds like the keys of the arrays you are generating are insignificant. If that's the case, you can do a simple merge then determine the unique ones with built in PHP functions:
$array = array_merge($array1, $array2, $array3);
$unique = array_unique($array);
edit: an example:
// Emulate the result of your get_post_meta() call.
$therapie = array(
array('Massagetherapie'),
array('Hot stone'),
array('Massagetherapie'),
);
$array = array();
foreach($therapie as $thera) {
$array = array_merge($array, $thera);
}
$unique = array_unique($array);
print_r($unique);
PHP's array_unique() will remove duplicate values from an array.
$tester = array();
foreach($therapie as $thera) {
array_push($tester, $thera);
}
$result = array_unique($tester);
print_r($result);

Reset/remove all values in an array in PHP

I have an array_flipped array that looks something like:
{ "a" => 0, "b" => 1, "c" => 2 }
Is there a standard function that I can use so it looks like (where all the values are set to 0?):
{ "a" => 0, "b" => 0, "c" => 0 }
I tried using a foreach loop, but if I remember correctly from other programming languages, you shouldn't be able to change the value of an array via a foreach loop.
foreach( $poll_options as $k => $v )
$v = 0; // doesn't seem to work...
tl; dr: how can I set all the values of an array to 0? Is there a standard function to do this?
$array = array_fill_keys(array_keys($array), 0);
or
array_walk($array, create_function('&$a', '$a = 0;'));
You can use a foreach to reset the values;
foreach($poll_options as $k => $v) {
$poll_options[$k] = 0;
}
array_fill_keys function is easiest one for me to clear the array. Just use like
array_fill_keys(array_keys($array), "")
or
array_fill_keys(array_keys($array), whatever you want to do)
foreach may cause to decrease your performance to be sure that which one is your actual need.
Run your loop like this, it will work:
foreach( $poll_options as $k => $v )
$poll_options[$k] = 0;
Moreover, ideally you should not be able to change the structure of the array while using foreach, but changing the values does no harm.
As of PHP 5.3 you can use lambda functions, so here's a functional solution:
$array = array_map(function($v){ return 0; }, $array);
You have to use an ampersand...
foreach( $poll_options as &$v)
$v = 0;
Or just use a for loop.
you can try this
foreach( $poll_options as $k => &$v )
$v = 0;
Address of $v
array_combine(array_keys($array), array_fill(0, count($array), 0))
Would be the least manual way of doing it.
There are two types for variable assignment in PHP,
Copy
Reference
In reference assignment, ( $a = &$b ), $a and $b both, refers to the same content. ( read manual )
So, if you want to change the array in thesame time as you doing foreach on it, there are two ways :
1- Making a copy of array :
foreach($array as $key=>$value){
$array[$key] = 0 ; // reassign the array's value
}
2 - By reference:
foreach($array as $key => &$value){
$value = 0 ;
}

Categories