I have a multidimensional array, the sub-arrays consist of further values, I would like for all sub-arrays that only have one value to be converted into a string. How can I successfully scan through a multidimensional array to get the result?
Below is a small section of the array as it is now.
[1] => Array
(
[name] => Array
(
[0] => Person's name
)
[organisation] => Array
(
[0] => This is their organisation
[1] => aka something else
)
[address] => Array
(
[0] => The street name
[1] => The town name
)
[e-mail] => Array
(
[0] => test#this.site.com
)
)
and here is how I would like it to end up
[1] => Array
(
[name] => Person's name
[organisation] => Array
(
[0] => This is their organisation
[1] => aka something else
)
[address] => Array
(
[0] => The street name
[1] => The town name
)
[e-mail] => test#this.site.com
)
This should do the trick.
function array2string(&$v){
if(is_array($v) && count($v)==1){
$v = $v[0];
}
}
array_walk($array, 'array2string');
Or as a one-liner, since I'm nuts.
array_walk($array, create_function('&$v', 'if(is_array($v) && count($v)==1){$v = $v[0];}'));
EDIT: It looks like that array is an element in a bigger array. You need to put this function inside of a foreach loop.
function array2string(&$v){
if(is_array($v) && count($v)==1){
$v = $v[0];
}
}
foreach($array as &$val){
array_walk($val, 'array2string');
}
Or using my crazy create_function one-liner.
foreach($array as &$val){
array_walk($val, create_function('&$v', 'if(is_array($v) && count($v)==1){$v = $v[0];}'));
}
This should work no matter how deep the array is.
Put this function in your code:
function array2string(&$v){
if(is_array($v)){
if(count($v, COUNT_RECURSIVE) == 1){
$v = $v[0];
return;
}
array_walk($v, 'array2string');
}
}
Then do this:
array_walk($array, 'array2string');
This PHP 5.3 code uses a closure. You can use a named function, too, if you want. It specifically checks for strings, and calls itself for nested arrays.
<?php
array_walk($array, $walker = function (&$value, $key) use (&$walker) {
if (is_array($value)) {
if (count($value) === 1 && is_string($value[0])) {
$value = $value[0];
} else {
array_walk($value, $walker);
}
}
});
Related
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));
Well this has been a headache.
I have two arrays;
$array_1 = Array
(
[0] => Array
(
[id] => 1
[name] => 'john'
[age] => 30
)
[1] => Array
(
[id] => 2
[name] => 'Amma'
[age] => 28
)
[2] => Array
(
[id] => 3
[name] => 'Francis'
[age] => 29
)
)
And another array
array_2 = = Array
(
[0] => Array
(
[id] => 2
[name] => 'Amma'
)
)
How can I tell that the id and name of $array_2 are the same as the id and name of $array_1[1] and return $array_1[1]['age']?
Thanks
foreach($array_1 as $id=>$arr)
{
if($arr["id"]==$array_2[0]["id"] AND $arr["name"]==$array_2[0]["name"])
{
//Do your stuff here
}
}
Well you can do it in a straightforward loop. I am going to write a function that takes the FIRST element in $array_2 that matches something in $array_1 and returns the 'age':
function getField($array_1, $array_2, $field)
{
foreach ($array_2 as $a2) {
foreach ($array_1 as $a1) {
$match = true;
foreach ($a2 as $k => $v) {
if (!isset($a1[$k]) || $a1[$k] != $a2[$k]) {
$match = false;
break;
}
}
if ($match) {
return $a1[$field];
}
}
}
return null;
}
Use array_diff().
In my opinion, using array_diff() is a more generic solution than simply comparing the specific keys.
Array_diff() returns a new array that represents all entries that exists in the first array and DO NOT exist in the second array.
Since your first array contains 3 keys and the seconds array contains 2 keys, when there's 2 matches, array_diff() will return an array containing the extra key (age).
foreach ($array_1 as $arr) {
if (count(array_diff($arr, $array_2[1])) === 1) {//meaning 2 out of 3 were a match
echo $arr['age'];//prints the age
}
}
Hope this helps!
I assume you want to find the age of somebody that has a known id and name.
This will work :
foreach ($array_1 as $val){
if($val['id']==$array_2[0]['id'] && $val['name']==$array_1[0]['name']){
$age = $val['age'];
}
}
echo $age;
Try looking into this.
http://www.w3schools.com/php/func_array_diff.asp
And
comparing two arrays in php
-Best
I have two multidimensional arrays. First one $properties contains english names and their values. My second array contains the translations. An example
$properties[] = array(array("Floor"=>"5qm"));
$properties[] = array(array("Height"=>"10m"));
$translations[] = array(array("Floor"=>"Boden"));
$translations[] = array(array("Height"=>"Höhe"));
(They are multidimensional because the contains more elements, but they shouldn't matter now)
Now I want to translate this Array, so that I its at the end like this:
$properties[] = array(array("Boden"=>"5qm"));
$properties[] = array(array("Höhe"=>"10m"));
I have managed to build the foreach construct to loop through these arrays, but at the end it is not translated, the problem is, how I tell the array to replace the key with the value.
What I have done is this:
//Translate Array
foreach ($properties as $PropertyArray) {
//need second foreach because multidimensional array
foreach ($PropertyArray as $P_KiviPropertyNameKey => $P_PropertyValue) {
foreach ($translations as $TranslationArray) {
//same as above
foreach ($TranslationArray as $T_KiviTranslationPropertyKey => $T_KiviTranslationValue) {
if ($P_KiviPropertyNameKey == $T_KiviTranslationPropertyKey) {
//Name found, save new array key
$P_KiviPropertyNameKey = $T_KiviTranslationValue;
}
}
}
}
}
The problem is with the line where to save the new key:
$P_KiviPropertyNameKey = $T_KiviTranslationValue;
I know this part is executed correctly and contains the correct variables, but I believe this is the false way to assing the new key.
This is the way it should be done:
$properties[$oldkey] = $translations[$newkey];
So I tried this one:
$PropertyArray[$P_KiviPropertyNameKey] = $TranslationArray[$T_KiviTranslationPropertyKey];
As far as I understood, the above line should change the P_KiviPropertyNameKey of the PropertyArray into the value of Translation Array but I do not receive any error nor is the name translated. How should this be done correctly?
Thank you for any help!
Additional info
This is a live example of the properties array
Array
(
[0] => Array
(
[country_id] => 4402
)
[1] => Array
(
[iv_person_phone] => 03-11
)
[2] => Array
(
[companyperson_lastname] => Kallio
)
[3] => Array
(
[rc_lot_area_m2] => 2412.7
)
[56] => Array
(
[floors] => 3
)
[57] => Array
(
[total_area_m2] => 97.0
)
[58] => Array
(
[igglo_silentsale_realty_flag] => false
)
[59] => Array
(
[possession_partition_flag] => false
)
[60] => Array
(
[charges_parkingspace] => 10
)
[61] => Array
(
[0] => Array
(
[image_realtyimagetype_id] => yleiskuva
)
[1] => Array
(
[image_itemimagetype_name] => kivirealty-original
)
[2] => Array
(
[image_desc] => makuuhuone
)
)
)
And this is a live example of the translations array
Array
(
[0] => Array
(
[addr_region_area_id] => Maakunta
[group] => Kohde
)
[1] => Array
(
[addr_town_area] => Kunta
[group] => Kohde
)
[2] => Array
(
[arable_no_flag] => Ei peltoa
[group] => Kohde
)
[3] => Array
(
[arableland] => Pellon kuvaus
[group] => Kohde
)
)
I can build the translations array in another way. I did this like this, because in the second step I have to check, which group the keys belong to...
Try this :
$properties = array();
$translations = array();
$properties[] = array("Floor"=>"5qm");
$properties[] = array("Height"=>"10m");
$translations[] = array("Floor"=>"Boden");
$translations[] = array("Height"=>"Höhe");
$temp = call_user_func_array('array_merge_recursive', $translations);
$result = array();
foreach($properties as $key=>$val){
foreach($val as $k=>$v){
$result[$key][$temp[$k]] = $v;
}
}
echo "<pre>";
print_r($result);
output:
Array
(
[0] => Array
(
[Boden] => 5qm
)
[1] => Array
(
[Höhe] => 10m
)
)
Please note : I changed the array to $properties[] = array("Floor"=>"5qm");, Removed a level of array, I guess this is how you need to structure your array.
According to the structure of $properties and $translations, you somehow know how these are connected. It's a bit vague how the indices of the array match eachother, meaning the values in $properties at index 0 is the equivalent for the translation in $translations at index 0.
I'm just wondering why the $translations array need to have the same structure (in nesting) as the $properties array. To my opinion the word Height can only mean Höhe in German. Representing it as an array would suggest there are multiple translations possible.
So if you could narrow down the $translations array to an one dimensional array as in:
$translation = array(
"Height"=>"Höhe",
"Floor"=>"Boden"
);
A possible loop would be
$result = array();
foreach($properties as $i => $array2) {
foreach($array2 as $i2 => $array3) {
foreach($array3 as $key => $value) {
$translatedKey = array_key_exists($key, $translations) ?
$translations[$key]:
$key;
$result[$i][$i2][$translatedKey] = $value;
}
}
}
(I see every body posting 2 loops, it's an array,array,array structure, not array,array ..)
If you cannot narrow down the translation array to a one dimensional array, then I'm just wondering if each index in the $properties array matches the same index in the $translations array, if so it's the same trick by adding the indices (location):
$translatedKey = $translations[$i][$i2][$key];
I've used array_key_exists because I'm not sure a translation key is always present. You have to create the logic for each case scenario yourself on what to check or not.
This is a fully recursive way to do it.
/* input */
$properties[] = array(array("Floor"=>"5qm", array("Test"=>"123")));
$properties[] = array(array("Height"=>"10m"));
$translations[] = array(array("Floor"=>"Boden", array("Test"=>"Foo")));
$translations[] = array(array("Height"=>"Höhe"));
function array_flip_recursive($arr) {
foreach ($arr as $key => $val) {
if (is_array($val)) {
$arr[$key] = array_flip_recursive($val);
}
else {
$arr = #array_flip($arr);
}
}
return $arr;
}
function array_merge_it($arr) {
foreach ($arr as $key => $val) {
if (is_array($val)) {
$arr[$key] = array_merge_it($val);
} else {
if(isset($arr[$key]) && !empty($arr[$key])) {
#$arr[$key] = $arr[$val];
}
}
}
return $arr;
}
function array_delete_empty($arr) {
foreach ($arr as $key => $val) {
if (is_array($val)) {
$arr[$key] = array_delete_empty($val);
}
else {
if(empty($arr[$key])) {
unset($arr[$key]);
}
}
}
return $arr;
}
$arr = array_replace_recursive($properties, $translations);
$arr = array_flip_recursive($arr);
$arr = array_replace_recursive($arr, $properties);
$arr = array_merge_it($arr);
$arr = array_delete_empty($arr);
print_r($arr);
http://sandbox.onlinephpfunctions.com/code/d2f92605b609b9739964ece9a4d8f389be4a7b81
You have to do the for loop in this way. If i understood you right (i.e) in associative array first key is same (some index).
foreach($properties as $key => $values) {
foreach($values as $key1 => $value1) {
$propertyResult[] = array($translations[$key][$key1][$value1] => $properties[$key][$key1][$value1]);
}
}
print_r($propertyResult);
I have an 2d array which returns me this values:
Array (
[0] => Array (
[0] => wallet,pen
[1] => perfume,pen
)
[1] => Array (
[0] => perfume, charger
[1] => pen,book
).
Out of this i would like to know if it is possible to create a function which would combine the array going this way,and create a new one :
if for example [0] => Array ( [0] => wallet,pen [1] => perfume,pen ) then should be equal to
[0] => Array ( [0] => wallet,pen, perfume ) because there is a common word else do nothing.
And also after that retrieve each words as strings for further operations.
How can i make the values of such an array unique. Array ( [0] => Array ( [0] => wallet [1] => pen [2] => perfume [3] => pen) ) as there is pen twice i would like it to be deleted in this way ( [0] => Array ( [0] => wallet [1] => pen [2] => perfume) )
It's just a matter of mapping the array and combining the inner arrays:
$x = [['wallet,pen', 'perfume,pen'], ['perfume,charger', 'pen,book']];
$r = array_map(function($item) {
return array_unique(call_user_func_array('array_merge', array_map(function($subitem) {
return explode(',', $subitem);
}, $item)));
}, $x);
Demo
This first splits all the strings based on comma. They are then merged together with array_merge() and the duplicates are removed using array_unique().
See also: call_user_func_array(), array_map()
Try this :
$array = Array (Array ( "wallet,pen", "perfume,pen" ), Array ( "perfume, charger", "pen,book" ));
$res = array();
foreach($array as $key=>$val){
$temp = array();
foreach($val as $k=>$v){
foreach(explode(",",$v) as $vl){
$temp[] = $vl;
}
}
if(count(array_unique($temp)) < count($temp)){
$res[$key] = implode(",",array_unique($temp));
}
else{
$res[$key] = $val;
}
}
echo "<pre>";
print_r($res);
output :
Array
(
[0] => wallet,pen,perfume
[1] => Array
(
[0] => perfume, charger
[1] => pen,book
)
)
You can eliminate duplicate values while pushing them into your result array by assigning the tag as the key to the element -- PHP will not allow duplicate keys on the same level of an array, so any re-encountered tags will simply be overwritten.
You can use recursion or statically written loops for this task.
Code: (Demo)
$result = [];
foreach ($array as $row) {
foreach ($row as $tags) {
foreach (explode(',', $tags) as $tag) {
$result[$tag] = $tag;
}
}
}
var_export(array_values($result));
Code: (Demo)
$result = [];
array_walk_recursive(
$array,
function($v) use(&$result) {
foreach (explode(',', $v) as $tag) {
$result[$tag] = $tag;
}
}
);
var_export(array_values($result));
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();