Maybe the title can not explain my question ,please see my example :
I have an multi-dimension array like this :
Array
(
[0] => Array
(
[name] => 'A'
[ec_dest_name] => 楽天testuser_998
),
[1] => Array
(
[name] => 'A'
[ec_dest_name] => 楽天testuser_998
),
[2] => Array
(
[name] => 'B'
[ec_dest_name] => 楽天testuser_998
),
[3] => Array
(
[name] => 'C'
[ec_dest_name] => 楽天testuser_998
)
)
I want to count the element by key name , it mean that I want to return an array like :
Array ('A' => 2 , 'B'=>1, 'C'=>1)
Any quick way to accomplish that , I could loop array and count but I think it is not a good idea
Thank in advanced
You can use array_count_values & array_column togather -
$counts = array_count_values(array_column($your_array, 'name'));
Output
array(3) {
["A"]=>
int(2)
["B"]=>
int(1)
["C"]=>
int(1)
}
Demo
As Mark Baker suggested for older PHP versions -
$counts = array_count_values(
array_map(function($value) {
return $value['name'];
}, $your_array)
);
You may as well do that with 2 Loops as shown below. You might test this also HERE.
<?php
$arrSections = array();
$arrCounts = array();
$arrMain = array(
array(
'name' => "A",
'ec_dest_name' => "楽天testuser_998",
),
array(
'name' => "A",
'ec_dest_name' => "楽天testuser_998",
),
array(
'name' => "B",
'ec_dest_name' => "楽天testuser_998",
),
array(
'name' => "C",
'ec_dest_name' => "楽天testuser_998",
),
);
// BUNDLE ARRAYS WITH SIMILAR name INTO ONE GROUP
// THUS CREATING A MULTI-DIMENSIONAL ARRAY WHOSE MAIN KEYS CORRESPOND TO
// THE name OF THE MEMBER ARRAYS IN THE GROUP.
foreach($arrMain as $iKey=>$subMain){
$name = $subMain['name'];
if(!array_key_exists($name, $arrSections)) {
$arrSections[$name] = array();
}
$arrSections[$name][] = $subMain;
}
// FETCH THE COUNTS OF EACH GROUP AND MAKE AN ARRAY OUT OF IT...
foreach($arrSections as $k=>$v){
$arrCounts[$k] = count($v);
}
var_dump($arrCounts);
//OUTPUTS::
array (size=3)
'A' => int 2
'B' => int 1
'C' => int 1
Related
I have two multidimensional arrays in php and want to merge them.
First one :
array1 = (
0 => array (
0 => array(
id => 1,
name => "test"
)
)
1 => array(...)
)
Second one :
array2 = (
0 => array (
0 => array(
id => 200,
name => "test"
),
1 => array(
id => 201,
name => "test"
)
)
1 => array(...)
)
And the merged array must be like this :
lastArray = (
0 => array (
0 => array(
id =>1,
name => "test"
),
1 => array(
id => 200,
name => "test"
),
2 => array (
id => 201,
name => "test"
)
)
1 => array(...)
)
How should I do this with a proper foreach loop?
According to the lastArray that you've presented - you need to merge the inner arrays only at 0 position/index(and you didn't show how should look a merge result at 1 index).Use the following approach:
$array1[0] = array_merge($array1[0], $array2[0]);
// now, $array1 is your $lastArray
Method 1:
Why not use array_merge or array-merge-recursive for this? This will merge the both (or more) arrays.
$array = array_merge($array1, $array2);
$array = array_merge-recursive($array1, $array2);
Method 2:
Loop through one array.
(You may check if the key is equal to the others array key).
Maybe something like this:
foreach($array_1 as $key=>$value) $array_2[$key] = $value;
Reminder from splash58: Don't forget to use usort in both methods to sort the array by values after sort by id
I need your help with my problem. My problem is I have 2 arrays the first one is the main array. The second is the array for my new data.
Let's say I have these arrays.
This is the main array:
Array
(
0 => Array
(
'id' => 1,
'name' => 'Apple',
'age' => 12
)
1 => Array
(
'id' => 2,
'name' => May,
'age' => 13
)
)
This is the second array:
Array
(
1 => Array
(
'gender' => 'Male'
)
2 => Array
(
'gender' => 'Female'
)
)
And I have this loop in PHP
foreach($main_array as &$main){
//this is the loop inside the first array
// how can I add the second array with it?
}
This is the sample output:
[0] => Array
(
[id] => 1
[name] => Apple
[age] => 12
[gender] => Female
)
[1] => Array
(
[id] => 2
[name] => May
[age] => 13
[gender] => Female
)
How can I do that? Any suggestions? That's all thanks.
for($i=0; $i<count($main_array); $i++){
for($j=0; $j<count($second_array); $j++){
if($main_array[$i]['id'] == $j){
$main_array[$i]['gender'] = $second_array[$j]['gender']
}
}
}
I fixed your example code, it wont run otherwise.
<?php
// Test data:
$main_array = Array(
0 => Array(
'id' => 1,
'name' => 'Apple',
'age' => 12
),
1 => Array (
'id' => 2,
'name' => 'May',
'age' => 13
)
);
$lookup = Array(
1 => Array(
'gender' => 'Male'
),
2 => Array(
'gender' => 'Female'
)
);
// Your answer:
foreach ($main_array as &$main) {
if (array_key_exists($main['id'],$lookup)) {
$main['gender'] = $lookup[$main['id']]['gender']; // <-- sets gender value
}
}
// Output it to browser:
echo '<pre>$main_array = '.print_r($main_array,true).'</pre>';
The array_key_exists() check is there to avoid errors such as PHP Notice: Undefined offset: 123 when the $lookup data is incomplete.
If you want to merge all of the data from both arrays:
PHP tools:
The exact behaviors of these functions needs to be studied and tested before usage, to make sure it fits your intent.
// array merge recursive doesn't merge numeric keys
$main_array = array_merge_recursive($main_array, $secondary_array);
// array replace recursive has a downside of replacing stuff
$main_array = array_replace_recursive($main_array, $secondary_array);
Rolling your own:
foreach($main_array as $i => &$main){
if(isset($secondary_array[$i])) {
foreach($secondary_array[$i] AS $key => $value) {
$main[$key] = $value;
}
}
}
Both of the above solutions only apply if the array-indexes of $main_array and $secondary_array match.
In your example your arrays don't match:
- $secondary_array[0] doesn't exist so $main_array[0] will not be populated with a 'gender' value;
- $main_array[2] doesn't exist so $main_array[2] will be created and it will only have a 'gender' value same as $secondary_array[2]['gender']
If you want to only merge some bits and pieces of the arrays:
Rolling your own:
foreach($main_array as $i => &$main) {
if(isset($secondary_array[$i])) and isset($secondary_array[$i]['gender'])) {
$main['gender'] = $secondary_array[$i]['gender'];
}
}
foreach($main_array as &$main){//this is the loop inside the first array
foreach($second_array as &$second){ //this is the loop inside the second array
}
}
foreach($arr1 as $k => $arr1Item) {
$arr1[$k]['gender'] = $arr2[$k]['gender'];
}
This question already has answers here:
Generate an associative array from an array of rows using one column as keys and another column as values
(3 answers)
Closed 7 months ago.
I am rewrting a newsletter-thingy.
I have a table for all newsletter fields, that is like this:
field_uid | field_name | field_content | field_letter_id
Where f.x. the column field_name can have the value letter_headline
and the column field_content can have the value My headline.
When I do this:
$fields = $this->db->dbh->query("SELECT field_name, field_content FROM newsletter_fields WHERE field_letter_uid = '". $letter_id ."'");
foreach($fields->fetchAll(PDO::FETCH_ASSOC) as $key) {
print_r($key);
}
It will correctly give me this:
Array ( [field_name] => letter_image0 [field_content] => image.jpg )
Array ( [field_name] => letter_headline [field_content] => My headline )
Array ( [field_name] => letter_headline_size [field_content] => 12 )
Array ( [field_name] => letter_sub_headline [field_content] => My subheadline )
Array ( [field_name] => letter_sub_headline_size [field_content] => 10 )
Array ( [field_name] => letter_content [field_content] => Letter content )
Array ( [field_name] => letter_link [field_content] => www.example.com )
Array ( [field_name] => letter_link_txt [field_content] => Example )
What I want is to build an array like this
$field["letter_image"] = "image.jpg";
$field["letter_headline"] = "My headline"
And then I can output the content with:
echo $field["letter_image"];
But I can't seem to figure out how to set the field array.
$result = array_combine(array_column($data, 'field_name'), $data);
This is an old question, but I think it is worth mentioning that [array_column][1] function can accept the name of the column to use as array keys as a third parameter, so the easiest solution for this is :
// field_content column will be used as values of the array
// field_name column will be used as keys
$result = array_column($data, 'field_content', 'field_name');
Applying this to the example of #Toskan's answer:
$x = [['id' => 5, 'name' => 'john'], ['id' => 15, 'name' => 'jim']];
$result = array_column($x, 'name', 'id');
print_r($result);
// outputs Array ( [5] => john [15] => jim )
Easiest solution is just iterate through your array, like:
$result = [];
foreach($data as $row)
{
$result[$row['field_name']] = $row['field_content'];
}
You'll probably want to do this in your fetch cycle (so you'll avoid then iterating through rows twice)
well, almas solution is not using the native implementation that is optimized.
I am not saying it is wrong, just not optimized.
This should be optimized:
$x = [['id' => 5, 'name' => 'john'], ['id' => 15, 'name' => 'jim']];
$keys = array_column($x, 'id');
$values = array_column($x, 'name');
$result = array_combine($keys, $values);
var_dump($result);
//outputs array(2) { [5]=> string(4) "john" [15]=> string(3) "jim" }
This does not work with PHP 4 and only works php > 5.5
Use the third parameter of array_column
$rows = [
[
'field_name' => 'letter_image',
'field_content' => 'image.jpg'
],
[
'field_name' => 'letter_headline',
'field_content' => 'My headline'
],
];
$fields = array_column($rows, 'field_content', 'field_name');
---
php > var_dump($fields);
array(2) {
["letter_image"]=> string(9) "image.jpg"
["letter_headline"]=> string(11) "My headline"
}
https://www.php.net/manual/es/function.array-column.php
Garh... Nevermind..
Fairly simple
$field[$key["field_name"]] = $key["field_content"];
This question already has answers here:
How do I Sort a Multidimensional Array in PHP [duplicate]
(10 answers)
Closed 9 years ago.
I've got an array of arrays like this :
Array(
[id1] => Array (
/* details */
[unique] => 3
)
[id2] => Array (
/* details */
[unique] => 5
[id3] => Array (
/* details */
[unique] => 1
)
)
Question : How could I sort it by the unique field, so that it is converted like the one following?
Array(
[id2] => Array (
/* details */
[unique] => 5
)
[id1] => Array (
/* details */
[unique] => 3
[id3] => Array (
/* details */
[unique] => 1
)
)
Classical task for usort function:
<?php
$data = array(
"id1" => Array (
"unique" => 3
),
"id2" => Array (
"unique" => 5),
"id3" => Array (
"unique" => 1
),
);
function cmp($a, $b)
// {{{
{
if ($a["unique"] == $b["unique"]) {
return 0;
}
return ($a["unique"] < $b["unique"]) ? 1 : -1;
}
// }}}
usort($data, "cmp");
var_dump($data);
Prints:
array(3) {
[0]=>
array(1) {
["unique"]=>
int(5)
}
[1]=>
array(1) {
["unique"]=>
int(3)
}
[2]=>
array(1) {
["unique"]=>
int(1)
}
}
http://www.php.net/manual/en/function.usort.php
using my custom function you can sort array
function multisort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii]=$va[$key];
}
asort($sorter);
foreach ($sorter as $ii => $va) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
}
multisort ($your_array,"order");
By using usort():
$array = array(
"id1" => array("unique" => 3),
"id2" => array("unique" => 5),
"id3" => array("unique" => 1),
);
usort($array, function ($a, $b){
if ($a['unique'] == $b) {
return 0;
}
return ($a['unique'] > $b['unique']) ? -1 : 1;
});
print_r($array);
Outputs:
Array
(
[0] => Array
(
[unique] => 5
)
[1] => Array
(
[unique] => 3
)
[2] => Array
(
[unique] => 1
)
)
I feel like I'm repeating myself, sorry :D
Do not hesitate to look at libraries from frameworks.
[CakePHP] made an awesome class which is able to navigate into arrays using a string in dot syntax notation. This library is known as Hash, just look at it.
The method Sort is used to sort an array with keys and values depending of what you put inside the "path" attribute.
It's more useful than others functions, because it sorts the array by keeping the indexes and all the other subvalues contained in this array, including more dimensional sub-arrays.
For your example :
$array = array(
'id1' => array (
'unique' => 3,
),
'id2' => array (
'unique' => 5,
),
'id3' => Array (
'unique' => 1,
),
);
Just write this :
/**
* First param: the array
* Second param : the "path" of the datas to save.
* "{s}" means "Matching any kind of index", for you to sort ALL indexes matching
* the dot "." is used to navigate into the array like an object
* And "unique" is the key which you want to be sorted by its value
* The third param is simply the order method, "ascending" or "descending"
*/
$sorted_array = Hash::sort($array, '{s}.unique', 'asc');
And $sorted_array will be equal to this :
array (
'id3' => array (
'unique' => 1,
),
'id1' => array (
'unique' => 3,
),
'id2' => array (
'unique' => 5,
),
);
I have an array
Array(
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[1] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[2] => Array
(
[0] => 33
[user_id] => 33
[1] => 8
[frame_id] => 8
)
[3] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[4] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
As you can see key 0 is the same as 1, 3 and 4. And key 2 is different from them all.
When running the array_unique function on them, the only left is
Array (
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
Any ideas why array_unique isn't working as expected?
It's because array_unique compares items using a string comparison. From the docs:
Note: Two elements are considered
equal if and only if (string) $elem1
=== (string) $elem2. In words: when the string representation is the same.
The first element will be used.
The string representation of an array is simply the word Array, no matter what its contents are.
You can do what you want to do by using the following:
$arr = array(
array('user_id' => 33, 'frame_id' => 3),
array('user_id' => 33, 'frame_id' => 3),
array('user_id' => 33, 'frame_id' => 8)
);
$arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
//result:
array
0 =>
array
'user_id' => int 33
'user' => int 3
2 =>
array
'user_id' => int 33
'user' => int 8
Here's how it works:
Each array item is serialized. This
will be unique based on the array's
contents.
The results of this are run through array_unique,
so only arrays with unique
signatures are left.
array_intersect_key will take
the keys of the unique items from
the map/unique function (since the source array's keys are preserved) and pull
them out of your original source
array.
Here's an improved version of #ryeguy's answer:
<?php
$arr = array(
array('user_id' => 33, 'tmp_id' => 3),
array('user_id' => 33, 'tmp_id' => 4),
array('user_id' => 33, 'tmp_id' => 5)
);
# $arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
$arr = array_intersect_key($arr, array_unique(array_map(function ($el) {
return $el['user_id'];
}, $arr)));
//result:
array
0 =>
array
'user_id' => int 33
'tmp_id' => int 3
First, it doesn't do unneeded serialization. Second, sometimes attributes may be different even so id is the same.
The trick here is that array_unique() preserves the keys:
$ php -r 'var_dump(array_unique([1, 2, 2, 3]));'
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[3]=>
int(3)
}
This let's array_intersect_key() leave the desired elements.
I've run into it with Google Places API. I was combining results of several requests with different type of objects (think tags). But I got duplicates, since an object may be put into several categories (types). And the method with serialize didn't work, since the attrs were different, namely, photo_reference and reference. Probably these are like temporary ids.
array_unique() only supports multi-dimensional arrays in PHP 5.2.9 and higher.
Instead, you can create a hash of the array and check it for unique-ness.
$hashes = array();
foreach($array as $val) {
$hashes[md5(serialize($val))] = $val;
}
array_unique($hashes);
array_unique deosn't work recursive, so it just thinks "this are all Arrays, let's kill all but one... here we go!"
Quick Answer (TL;DR)
Distinct values may be extracted from PHP Array of AssociativeArrays using foreach
This is a simplistic approach
Detailed Answer
Context
PHP 5.3
PHP Array of AssociativeArrays (tabluar composite data variable)
Alternate name for this composite variable is ArrayOfDictionary (AOD)
Problem
Scenario: DeveloperMarsher has a PHP tabular composite variable
DeveloperMarsher wishes to extract distinct values on a specific name-value pair
In the example below, DeveloperMarsher wishes to get rows for each distinct fname name-value pair
Solution
example01 ;; DeveloperMarsher starts with a tabluar data variable that looks like this
$aodtable = json_decode('[
{
"fname": "homer"
,"lname": "simpson"
},
{
"fname": "homer"
,"lname": "jackson"
},
{
"fname": "homer"
,"lname": "johnson"
},
{
"fname": "bart"
,"lname": "johnson"
},
{
"fname": "bart"
,"lname": "jackson"
},
{
"fname": "bart"
,"lname": "simpson"
},
{
"fname": "fred"
,"lname": "flintstone"
}
]',true);
example01 ;; DeveloperMarsher can extract distinct values with a foreach loop that tracks seen values
$sgfield = 'fname';
$bgnocase = true;
//
$targfield = $sgfield;
$ddseen = Array();
$vout = Array();
foreach ($aodtable as $datarow) {
if( (boolean) $bgnocase == true ){ #$datarow[$targfield] = #strtolower($datarow[$targfield]); }
if( (string) #$ddseen[ $datarow[$targfield] ] == '' ){
$rowout = array_intersect_key($datarow, array_flip(array_keys($datarow)));
$ddseen[ $datarow[$targfield] ] = $datarow[$targfield];
$vout[] = Array( $rowout );
}
}
//;;
print var_export( $vout, true );
Output result
array (
0 =>
array (
0 =>
array (
'fname' => 'homer',
'lname' => 'simpson',
),
),
1 =>
array (
0 =>
array (
'fname' => 'bart',
'lname' => 'johnson',
),
),
2 =>
array (
0 =>
array (
'fname' => 'fred',
'lname' => 'flintstone',
),
),
)
Pitfalls
This solution does not aggregate on fields that are not part of the DISTINCT operation
Arbitrary name-value pairs are returned from arbitrarily chosen distinct rows
Arbitrary sort order of output
Arbitrary handling of letter-case (is capital A distinct from lower-case a ?)
See also
php array_intersect_key
php array_flip
function array_unique_recursive($array)
{
$array = array_unique($array, SORT_REGULAR);
foreach ($array as $key => $elem) {
if (is_array($elem)) {
$array[$key] = array_unique_recursive($elem);
}
}
return $array;
}
Doesn't that do the trick ?
`
$arr = array(
array('user_id' => 33, 'tmp_id' => 3),
array('user_id' => 33, 'tmp_id' => 4),
array('user_id' => 33, 'tmp_id' => 3),
array('user_id' => 33, 'tmp_id' => 4),
);
$arr1 = array_unique($arr,SORT_REGULAR);
echo "<pre>";
print_r($arr1);
echo "</pre>";
Array(
[0] => Array(
[user_id] => 33
[tmp_id] => 3
)
[1] => Array(
[user_id] => 33
[tmp_id] => 4
)
)
`