Php Get the key of a array based in a string [duplicate] - php

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to search by key=>value in a multidimensional array in PHP
PHP search for Key in multidimensional array
How can I search in a array values and get the key?
Example:
search for id 1 = key 0
or
search for name Frank = key 1
Array
(
[0] => Array
(
[id] => 1
[name] => Bob
[url] => http://www.bob.com.br
)
[1] => Array
(
[id] => 2
[name] => Frank
[url] => http://www.frank.com.br
)
)
Thks.
Adriano

Use array_search
foreach($array as $value) {
$result = array_search('Frank', $value);
if($result !== false) break;
}
echo $result

If you do not know the depth, you can do something like the following, which employs the use of RecursiveIteratorIterator and RecursiveArrayIterator:
<?php
/*******************************
* array_multi_search
*
* #array array to be searched
* #input search string
*
* #return array(s) that match
******************************/
function array_multi_search($array, $input){
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach($iterator as $id => $sub){
$subArray = $iterator->getSubIterator();
if(#strstr(strtolower($sub), strtolower($input))){
$subArray = iterator_to_array($subArray);
$outputArray[] = array_merge($subArray, array('Matched' => $id));
}
}
return $outputArray;
}

don't think there is a predifned function for that,
but here is one:
function sub_array_search($array, $sub_key, $value, $strict = FALSE)
{
foreach($array as $key => $sub_array)
{
if($sub_array[$sub_key] == $value)
{
if(!$strict OR $sub_array[$sub_key] === $value)
{
return $key;
}
}
}
return FALSE;
}

Related

Merging arrays recursively PHP

I am using this function two merge recursively arrays:
function array_merge_recursive_distinct(array &$array1, array &$array2) {
$merged = $array1;
foreach($array2 as $key => &$value) {
if(is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
$merged[$key] = array_merge_recursive_distinct($merged[$key], $value);
} else {
$merged[$key] = $value;
}
}
return $merged;
}
For using this function I am doing the following steps:
Declare an empty array $outArray = array();
Doing a while loop where I collect the information I need
During the while loop I call the array_merge_recursive_distinct function to fill the empty array recursively
However the final array contains only the last information it was gathered during the last while loop. I have tried to find a solution but I haven't succeed until now. What Am I doing wrong?
The recursive function takes all the info during the while loops (I have printed the input arrays in the recursive function) but it seems like it overwrites the merged array over and over again.
Thanks
CakePHP have a nice class called Hash, it implements a method called merge() who does exactly what you need
/**
* This function can be thought of as a hybrid between PHP's `array_merge` and `array_merge_recursive`.
*
* The difference between this method and the built-in ones, is that if an array key contains another array, then
* Hash::merge() will behave in a recursive fashion (unlike `array_merge`). But it will not act recursively for
* keys that contain scalar values (unlike `array_merge_recursive`).
*
* Note: This function will work with an unlimited amount of arguments and typecasts non-array parameters into arrays.
*
* #param array $data Array to be merged
* #param mixed $merge Array to merge with. The argument and all trailing arguments will be array cast when merged
* #return array Merged array
* #link http://book.cakephp.org/2.0/en/core-utility-libraries/hash.html#Hash::merge
*/
function merge_arrays_recursivelly(array $data, $merge) { // I changed the function name from merge to merge_arrays_recursivelly
$args = array_slice(func_get_args(), 1);
$return = $data;
foreach ($args as &$curArg) {
$stack[] = array((array) $curArg, &$return);
}
unset($curArg);
while (!empty($stack)) {
foreach ($stack as $curKey => &$curMerge) {
foreach ($curMerge[0] as $key => &$val) {
if (!empty($curMerge[1][$key]) && (array) $curMerge[1][$key] === $curMerge[1][$key] && (array) $val === $val) {
$stack[] = array(&$val, &$curMerge[1][$key]);
} elseif ((int) $key === $key && isset($curMerge[1][$key])) {
$curMerge[1][] = $val;
} else {
$curMerge[1][$key] = $val;
}
}
unset($stack[$curKey]);
}
unset($curMerge);
}
return $return;
}
https://book.cakephp.org/2.0/en/core-utility-libraries/hash.html#Hash::merge
Hash::merge source code
Perhaps something like this might be handy.
function array_merge_recursive_distinct(array &$array1, array &$array2) {
$merged = array_merge($array1,$array2);
asort($merged);
$merged = array_values(array_unique($merged));
return $merged;
}
$array1 = [];
$array2 = [1,2,3,4,5];
print_r(array_merge_recursive_distinct($array1,$array2));
$array1 = [1,2,3,6,12,19];
$array2 = [1,2,3,4,5];
print_r(array_merge_recursive_distinct($array1,$array2));
// output
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 12
[7] => 19
)
Test it on PHP Sandbox

Replace key of array with the value of another array while looping through

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);

How to change array key of this array? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
In PHP, how do you change the key of an array element?
This the array
Array
(
[0] => Array
(
[id] => 1
[due_date] => 2011-09-23
[due_amount] => 10600.00
)
[1] => Array
(
[id] => 2
[due_date] => 2011-10-23
[due_amount] => 10600.00
)
[2] => Array
(
[id] => 3
[due_date] => 2011-11-23
[due_amount] => 10600.00
)
)
how to change id to u_id in this array?
Regards
array_walk_recursive($array, 'changeIDkey');
function changeIDkey($item, &$key)
{
if ($key == 'id') $key = 'u_id';
}
PHP Manual: array_walk_recursive
EDIT
This will not work for the reason #salathe gave in the Comments below. Working on alternative.
ACTUAL ANSWER
function changeIDkey(&$value,$key)
{
if ($value === "id") $value = "u_id";
}
$new = array();
foreach ($array as $key => $value)
{
$keys = array_keys($value);
array_walk($keys,"changeIDkey");
$new[] = array_combine($keys,array_values($value));
}
var_dump($new); //verify
Where $array is your input array. Note that this will only work with your current array structure (two-dimensions, changes keys on only second dimension).
The loop iterates through the inner arrays changing "id" to "u_id" in the keys and then recombines the new keys with the old values.
foreach( $array as &$element ) {
$element['u_id'] = $element['id'];
unset( $element['id'] );
}

Simplify a nested array into a single level array [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How to Flatten a Multidimensional Array?
Let's say I have an array like this:
array (
1 =>
array (
2 =>
array (
16 =>
array (
18 =>
array (
),
),
17 =>
array (
),
),
),
14 =>
array (
15 =>
array (
),
),
)
How would I go about tranforming it into array like this?
array(1,2,16,18,17,14,15);
Sorry for the closevote. Didnt pay proper attention about you wanting the keys. Solution below:
$iterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator($arr),
RecursiveIteratorIterator::SELF_FIRST);
$keys = array();
and then either
$keys = array();
foreach($iterator as $key => $val) {
$keys[] = $key;
}
or with the iterator instance directly
$keys = array();
for($iterator->rewind(); $iterator->valid(); $iterator->next()) {
$keys[] = $iterator->key();
}
or more complicated than necessary
iterator_apply($iterator, function(Iterator $iterator) use (&$keys) {
$keys[] = $iterator->key();
return TRUE;
}, array($iterator));
gives
Array
(
[0] => 1
[1] => 2
[2] => 16
[3] => 18
[4] => 17
[5] => 14
[6] => 15
)
how about some recursion
$result = array();
function walkthrough($arr){
$keys = array_keys($arr);
array_push($result, $keys);
foreach ($keys as $key)
{
if (is_array($arr[$key]))
walkthrough($arr[$key]);
else
array_push($result,$arr[$key]);
}
return $result;
}
walkthrouth($your_arr);
P.S.:Code can be bugged, but you've got an idea :)
function flattenArray($array) {
$arrayValues = array();
foreach (new RecursiveIteratorIterator( new RecursiveArrayIterator($array)) as $val) {
$arrayValues[] = $val;
}
return $arrayValues;
} // function flattenArrayIndexed()
If we consider the nested array as a tree structure, you can apply depth first traversal to convert it into a list. That is, into a single array you desire.
I have searched all similar questions and it seems there is no way without a recursion that would keep the keys order intact.
So I just went with classic recursion:
function getArrayKeysRecursive(array $theArray)
{
$aArrayKeys = array();
foreach ($theArray as $k=>$v) {
if (is_array($v)) {
$aArrayKeys = array_merge($aArrayKeys, array($k), getArrayKeysRecursive($v));
} else {
$aArrayKeys = array_merge($aArrayKeys, array($k));
}
}
return $aArrayKeys;
}

PHP : flatten array - fastest way? [duplicate]

This question already has answers here:
How to Flatten a Multidimensional Array?
(31 answers)
Closed 5 months ago.
Is there any fast way to flatten an array and select subkeys ('key'&'value' in this case) without running a foreach loop, or is the foreach always the fastest way?
Array
(
[0] => Array
(
[key] => string
[value] => a simple string
[cas] => 0
)
[1] => Array
(
[key] => int
[value] => 99
[cas] => 0
)
[2] => Array
(
[key] => array
[value] => Array
(
[0] => 11
[1] => 12
)
[cas] => 0
)
)
To:
Array
(
[int] => 99
[string] => a simple string
[array] => Array
(
[0] => 11
[1] => 12
)
)
Give this a shot:
$ret = array();
while ($el = each($array)) {
$ret[$el['value']['key']] = $el['value']['value'];
}
call_user_func_array("array_merge", $subarrays) can be used to "flatten" nested arrays.
What you want is something entirely different. You could use array_walk() with a callback instead to extract the data into the desired format. But no, the foreach loop is still faster. There's no array_* method to achieve your structure otherwise.
Hopefully it will help someone else, but here is a function I use to flatten arrays and make nested elements more accessible.
Usage and description here:
https://totaldev.com/flatten-multidimensional-arrays-php/
The function:
// Flatten an array of data with full-path string keys
function flat($array, $separator = '|', $prefix = '', $flattenNumericKeys = false) {
$result = [];
foreach($array as $key => $value) {
$new_key = $prefix . (empty($prefix) ? '' : $separator) . $key;
// Make sure value isn't empty
if(is_array($value)) {
if(empty($value)) $value = null;
else if(count($value) == 1 && isset($value[0]) && is_string($value[0]) && empty(trim($value[0]))) $value = null;
}
$hasStringKeys = is_array($value) && count(array_filter(array_keys($value), 'is_string')) > 0;
if(is_array($value) && ($hasStringKeys || $flattenNumericKeys)) $result = array_merge($result, flat($value, $separator, $new_key, $flattenNumericKeys));
else $result[$new_key] = $value;
}
return $result;
}
This should properly combine arrays with integer keys. If the keys are contiguous and start at zero, they will be dropped. If an integer key doesn't yet exist in the flat array, it will be kept as-is; this should mostly preserve non-contiguous arrays.
function array_flatten(/* ... */)
{
$flat = array();
array_walk_recursive(func_get_args(), function($value, $key)
{
if (array_key_exists($key, $flat))
{
if (is_int($key))
{
$flat[] = $value;
}
}
else
{
$flat[$key] = $value;
}
});
return $flat;
}
You could use !isset($key) or empty($key) instead to favor useful values.
Here's a more concise version:
function array_flatten(/* ... */)
{
$flat = array();
array_walk_recursive(func_get_args(), function($value, $key) use (&$flat)
{
$flat = array_merge($flat, array($key => $value));
});
return $flat;
}

Categories