How to give names to arrays inside RecursiveArrayIterator? - php

Originally, I manually created nested foreach loops:
$first_array_counter = 0;
$second_array_counter = 0;
$third_array_counter= 0;
$fourth_array_counter = 0;
foreach ($nested_array_4_layers as $layer1_items) {
$first_array['first_array_id'] = $first_array_counter;
foreach ($layer1_items as $layer2_items) {
$second_array['second_array_id'] = $second_array_counter;
foreach ($layer2_items as $layer3_items) {
$third_array['third_array_id'] = $third_array_counter;
foreach ($layer3_items as $layer3_items) {
$fourth_array['fourth_array_id'] = $fourth_array_counter;
$fourth_array_counter++;
}
$third_array_counter++;
}
$second_array_counter++
}
$first_array_counter++;
}
But now I'm trying to change the code to be dynamic and with varying nesting levels. For example with 3 nesting levels and different names:
foreach ($nested_array_3_layers as $layer1_items) {
$other_first_array['first_array_id'] = $first_array_counter;
foreach ($layer1_items as $layer2_items) {
$other_second_array['second_array_id'] = $second_array_counter;
foreach ($layer2_items as $layer3_items) {
$other_third_array['third_array_id'] = $third_array_counter;
$third_array_counter++;
}
$second_array_counter++
}
$first_array_counter++;
}
For that I changed the code to use RecursiveIteratorIterator with RecursiveArrayIterator:
$iter = new RecursiveIteratorIterator(new RecursiveArrayIterator($nested_array_x_layers), RecursiveIteratorIterator::SELF_FIRST);
foreach ($iter as $k => $v) {
if (!is_array($v)) {
}
}
But I still want to be able to control which names the arrays have because I need to later use them.
Would that be done using maybe a switch-case and given options for the array names?
But then, how can I control which nesting level belongs to which name?

It is not recommended to use many loops at the same time, by defining keys, combining the arrays first will provide ease of use later.
Table 1
$array_1_data = Array (
[0] => Array ( [id] => 1 [name] => IT [slug] => it )
[1] => Array ( [id] => 2 [name] => Accounting [slug] => accounting )
)
Table 2
$array_2_data = Array (
[0] => Array ( [cid] => 3 [jid] => 24061 )
[1] => Array ( [cid] => 1 [jid] => 24062 )
)
Joining via key
$result = array_uintersect_uassoc($array_1_data, $array_2_data, function($a, $b){
return strcasecmp($a['id'], $b['cid']);
}, function($a, $b){
return (int) [$a, $b] == ['id', 'cid'];
});
conclusion
Array
(
[0] => Array
(
[id] => 1
[name] => IT
[slug] => it
)
)

Related

Array unique values PHP

I want to find the Unique values by username:
so the resulting array would be [0] =>JakeP, [1]=>TomC
My code currently works, but I was wondering is there a better way to accomplish this task with less loops, or using array_unique function?
Array
(
[0] => Array
(
[ID] => 3
[Username] => TomC
[Project_Name] => Inventory
)
[1] => Array
(
[ID] => 4
[Username] => JakeP
[Project_Name] => Inventory
)
[2] => Array
(
[ID] => 2
[Username] => TomC
[Project_Name] => Stocks
)
[3] => Array
(
[ID] => 1
[Username] => Tomc
[Project_Name] => Stocks
)
)
My code which works is :
$names_filter = array();
foreach($latest_projects as $project)
{
if(empty($names_filter))
{
$names_filter[] = $project['Username'];
}
else {
foreach($names_filter as $key=>$value)
{
if($value == $project['Username'])
{ break; }
else
{
$names_filter[] = $project['Username'];
}
}
}
}
If you're using PHP >= 5.5 you can take advantage of the array_column() function:
$uniqueNames = array_unique(
array_column($myArray, 'Username')
);
Prior to PHP 5.5, you can use:
$uniqueNames = array_unique(
array_map(
function($value) {
return $value['Username'];
},
$myArray
)
);
You can use the in_array function to simplify your code. Example:
$names_filter = array();
foreach($latest_projects as $project)
{
if(!in_array($project['Username'], $names_filter))
{
$names_filter[] = $project['Username'];
}
}
The in_array() function checks for the existence of a value in an array. So the foreach loop will only add a project username to the $names_filter array if it's not in the array. The output should be a list of unique usernames in the $names_filter array.
We can loop through $latest_projects and store each user name to new array ($filter). Since array can't have two elements with same keys, if the key exists it will be overwritten.
$filter = array();
foreach ($latest_projects as $project)
{
$filter[$project['Username']] = 1;
}
$filter = array_keys($filter);
I can't speak to the performance of this over other solutions, but a similar effect can be achieved with the use of array_map and array_unique. It's not as readable either though, which is just as important.
$uniqueUsers = array_unique(array_map(function ($p) { return $p['Username']; }, $latest_projects));

Getting multi dimensional array to create new arrays based on index value

I am having a terrible time getting this to work I have been struggling with it for a couple hours now. Can someone please help me? I have included a fiddle.
I believe my problem is in this string:
$$salesAndOwner[$i]["$salesAndOwner[$i]".$l] = $salesAndOwner[$i.$l][$param] = $values[$l];
Basically I have the following multidimensional array:
[sales] => Array
(
[FirstName] => Array
(
[0] => salesFirst1
[1] => salesFirst2
)
[LastName] => Array
(
[0] => salesLast1
[1] => salesLast2
)
)
[decisionmaker] => Array
(
[FirstName] => Array
(
[0] => dmFirst1
[1] => dmFirst2
)
[LastName] => Array
(
[0] => dmLast1
[1] => dmLast2
)
)
)
I need this to be reorganized like I did with the following array:
Array
(
[additionallocations0] => Array
(
[Address] => Address1
[State] => State1
)
[additionallocations1] => Array
(
[Address] => Address2
[State] => State2
)
)
Here is the original:
Array
(
[additionallocations] => Array
(
[Address] => Array
(
[0] => Address1
[1] => Address2
)
[State] => Array
(
[0] => State1
[1] => State2
)
)
This is how I reorganize the above array:
if(isset($_POST['additionallocations'])) {
$qty = count($_POST['additionallocations']["Address"]);
for ($l=0; $l<$qty; $l++)
{
foreach($_POST['additionallocations'] as $param => $values)
{
$additional['additionallocations'.$l][$param] = $values[$l];
}
}
And this is what I am using for the sales and decisionmaker array. If you notice I have an array that contains sales and decisionmaker in it. I would like to be able to sort any future arrays by just adding its primary arrays name. I feel I am close to solving my problem but I can not get it to produce right.
$salesAndOwner = array(0 => "sales", 1 => "decisionmaker");
for($i = 0; $i < 2; $i++){
$qty = count($_POST[$salesAndOwner[$i]]["FirstName"]);
for ($l=0; $l<$qty; $l++)
{
foreach($_POST[$salesAndOwner[$i]] as $param => $values)
{
$$salesAndOwner[$i]["$salesAndOwner[$i]".$l] = $salesAndOwner[$i.$l][$param] = $values[$l];
}
}
}
In the above code I hard coded 'sales' into the variable I need it to make a variable name dynamically that contains the sales0 decisionmaker0 and sales1 decisionmaker1 arrays so $sales and $decisionmaker
I hope this makes sense please let me know if you need any more info
Let's break it down. Using friendly variable names and spacing will make your code a lot easier to read.
Remember. The syntax is for you to read and understand easily. (Not even just you, but maybe future developers after you!)
So you have an array of groups. Each group contains an array of attributes. Each attribute row contains a number of attribute values.
PHP's foreach is a fantastic way to iterate through this, because you will need to iterate through (and use) the index names of the arrays:
<?php
$new_array = array();
// For each group:
foreach($original_array as $group_name => $group) {
// $group_name = e.g 'sales'
// For each attribute in this group:
foreach($group as $attribute_name => $attributes) {
// $attribute_name = e.g. 'FirstName'
// For each attribute value in this attribute set.
foreach($attributes as $row_number => $attribute) {
// E.g. sales0
$row_key = $group_name . $row_number;
// if this is the first iteration, we need to declare the array.
if(!isset($new_array[$row_key])) {
$new_array[$row_key] = array();
}
// e.g. Array[sales0][FirstName]
$new_array[$row_key][$attribute_name] = $attribute;
}
}
}
?>
With this said, this sort of conversion may cause unexpected results without sufficient validation.
Make sure the input array is valid (e.g. each attribute group has the same number of rows per group) and you should be okay.
$salesAndOwner = array("sales", "decisionmaker");
$result = array();
foreach ($salesAndOwner as $key) {
$group = $_POST[$key];
$subkeys = array_keys($group);
$first_key = $subkeys[0];
foreach ($group[$first_key] as $i => $val) {
$prefix = $key . $i;
foreach ($subkeys as $subkey) {
if (!isset($result[$prefix])) {
$result[$prefix] = array();
}
$result[$prefix][$subkey] = $val;
}
}
}
DEMO
Try
$result =array();
foreach($arr as $key=>$val){
foreach($val as $key1=>$val1){
foreach($val1 as $key2=>$val2){
$result[$key.$key2][$key1] = $val2;
}
}
}
See demo here

PHP Sort Mega-Array by Value

I am looking for some advices how could I sort this kind of Array by 'variant_name' key.
Because Array is really huge I minified it to the looking result state.
...
$filter[2413][1][81][sub_id] = 1;
$filter[2413][1][81][variant_id] = 81;
$filter[2413][1][81][variant_name] = 'Banana';
$filter[2413][2][87][sub_id] = 2;
$filter[2413][2][87][variant_id] = 87;
$filter[2413][2][87][variant_name] = 'Apple';
$filter[2413][3][32][sub_id] = 3;
$filter[2413][3][32][variant_id] = 32;
$filter[2413][3][32][variant_name] = 'Carrot';
...
Keys $filter[x][x][x] are not sequential.
I have tried the sort function I used before but it doesn't work with this kind of Array:
function array_sort_by_column(&$arr, $col, $dir = SORT_ASC) {
$sort_col = array();
foreach ($arr as $key=> $row) {
$sort_col[$key] = $row[$col];
}
array_multisort($sort_col, $dir, $arr);
}
array_sort_by_column($filter[][][], 'variant_name');
My target is modify array by sorting 'variant_name' to 'Apple', 'Banana', 'Carrot' accordingly keeping the array structure.
It's a working code tested from given examples.
Note that my codes still can be optimized, etc. Just take it as my advice.
TL;DR = Use usort().
function mySort($a,$b)
{
$av = "";
$bv = "";
foreach($a as $ak)
$av = $ak['variant_name'];
foreach($b as $bk)
$bv = $bk['variant_name'];
if($av[0] < $bv[0])
return false;
else return true;
}
How to use it? You have to specify which first level array to sort.
usort($filter['2413'],"mySort");
Then the result I got is:
Array
(
[2413] => Array
(
[0] => Array
(
[87] => Array
(
[sub_id] => 2
[variant_id] => 87
[variant_name] => Apple
)
)
[1] => Array
(
[81] => Array
(
[sub_id] => 1
[variant_id] => 81
[variant_name] => Banana
)
)
[2] => Array
(
[32] => Array
(
[sub_id] => 3
[variant_id] => 32
[variant_name] => Carrot
)
)
)
)

most common values in a multidemensional array

My question is maybe repetitive but I really find it hard. (I have read related topics)
This is the array :
Array
(
[0] => Array
(
[legend] => 38440
)
[1] => Array
(
[bestw] => 9765
)
[2] => Array
(
[fiuna] => 38779
)
[3] => Array
(
[adam] => 39011
)
[4] => Array
(
[adam] => 39011
)
[5] => Array
(
[adam] => 39011
)
)
I have tried many ways to handle this array and find out the most common value. The result I expect is "adam"
$countwin = array_count_values($winnernames);
$maxwin = max($countwin);
$mostwinner = array_keys($countswin, $maxwin);
EDIT : My array is like this array("A"=>"1" , "B"=>"2" , "A"=>"1") it should return A is the most common
How about iterating your array and counting the values you've got?
$occurences = array();
foreach ($data as $row) {
foreach ($row as $key => $score) {
if (empty($occurences[$key])) {
$occurences[$key] = 1;
} else {
$occurences[$key]++;
}
}
}
and then sorting that
arsort($occurences);
and grabbing the first element of the sorted array
$t = array_keys($occurences);
$winner = array_shift($occurences);
You may try this code. A brute force method indeed. But a quick search made me to find this an useful one:
function findDuplicates($data,$dupval) {
$nb= 0;
foreach($data as $key => $val)
if ($val==$dupval) $nb++;
return $nb;
}
EDIT : Sorry, I misinterpreted your question! But it might be the first hint of finding the one with maximum counter.

Loop an array of array

in PHP, how can i loop an array of array without know if is or not an array?
Better with an example:
Array
(
[0] => Array
(
[0] => big
[1] => small
)
[1] => Array
(
[0] => big
[1] => tiny
)
[2] => Array
(
[0] => a
[1] => b
[2] => c
[3] => d
[4] => e
[5] => f
)
[3] => row
[4] => cols
[5] => blablabla
[6] => Array
(
[0] => asd
[1] => qwe
)
}
any idea? thanks.
Which approach to choose depends on what you want to do with the data.
array_walk_recursive [docs] lets you traverse an array of arrays recursively.
You can use is_array to check if that element is an array, if it is, loop over it recursively.
You can use is_array to check if something is an array, and/or you can use is_object to check if it can be used within foreach:
foreach ($arr as $val)
{
if (is_array($val) || is_object($val))
{
foreach ($val as $subval)
{
echo $subval;
}
}
else
{
echo $val;
}
}
Another alternative is to use a RecursiveIteratorIterator:
$it = new RecursiveIteratorIterator(
new RecursiveArrayIterator($arr),
RecursiveIteratorIterator::SELF_FIRST);
foreach($it as $value)
{
# ... (each value)
}
The recursive iterator works for multiple levels in depth.
foreach( $array as $value ) {
if( is_array( $value ) ) {
foreach( $value as $innerValue ) {
// do something
}
}
}
That would work if you know it will be a maximum of 2 levels of nested array. If you don't know how many levels of nesting then you will need to use recursion. Or you can use a function such as array_walk_recursive
$big_array = array(...);
function loopy($array)
{
foreach($array as $element)
{
if(is_array($element))
{
// Keep looping -- IS AN ARRAY--
loopy($element);
}
else
{
// Do something for this element --NOT AN ARRAY--
}
}
}
loopy();

Categories