Recreate Multidimensional Array in PHP - php

This is pretty basic, but my question is:
Given an array:
$a = array(
0 => array('Rate'=> array('type_id'=>1, 'name' => 'Rate_1', 'type'=>'day','value'=>10)),
1 => array('Rate'=> array('type_id'=>1, 'name' => 'Rate_2', 'type'=>'night','value'=>8)),
2 => array('Rate'=> array('type_id'=>2, 'name' => 'Rate_3', 'type'=>'day','value'=>7)),
3 => array('Rate'=> array('type_id'=>2, 'name' => 'Rate_4', 'type'=>'nigh','value'=>16)),
4 => array('Rate'=> array('type_id'=>3, 'name' => 'Rate_5', 'type'=>'day','value'=>10))
);
What is the most efficient way to change it so we have something like:
$new_array = array(
[type_id] => array(
[type] => array(
[value]
)
)
)
);
In other words, I would like to strip some data (the name, which I don't need) and reorganise the dimensions of the array. In the end I would have an array which I would be able to access the values by $new_array['type_id']['type']['value'].

Not entirely sure if this is exactly what you want, but with this you can access the values by saying
echo $new[TYPE_ID][DAY_OR_NIGHT];
$new = array();
foreach($a AS $b){
$c = $b['Rate'];
$new[$c['type_id']][$c['type']] = $c['value'];
}
Using print_r on $new would give you:
Array
(
[1] => Array
(
[day] => 10
[night] => 8
)
[2] => Array
(
[day] => 7
[night] => 16
)
[3] => Array
(
[day] => 10
)
)

Since php 5.3.0, array_reduce() allows using an array as the initial value, given your initial array $a, you can use the following code
function my_reducer ($result, $item) {
$result[$item['Rate']['type_id']][$item['Rate']['type']] = $item['Rate']['value'];
return $result;
}
$assoc_arr = array_reduce($a, 'my_reducer', array());
var_dump($assoc_arr);
This returns
array(3) { [1]=> array(2) {
["day"]=>
int(10)
["night"]=>
int(8) } [2]=> array(2) {
["day"]=>
int(7)
["nigh"]=>
int(16) } [3]=> array(1) {
["day"]=>
int(10) } }

Related

How to remove specific element from array in php

I have the following array
Array
(
[tags] => Array
(
[0] => hello
)
[assignee] => 60b6a8a38cf91900695dd46b
[multiple_assignee] => Array
(
[0] => Array
(
[accountId] => 60b6a8a38cf91900695dd46b
)
[1] => Array
(
[accountId] => 5b39d23d32e26a2de15f174f
)
)
)
I want to remove 60b6a8a38cf91900695dd46b from the multiple_assignee array.
I have tried with the following code:
if (($key = array_search($this->getUsersHashMapValue($responsiblePartyIds[0]), $mutipleAssignee)) !== false) {
unset($mutipleAssignee[$key]['accountId']);
}
But it is not removing that element. The intention is I don't want to repeat the 60b6a8a38cf91900695dd46b assignee in the multiple assignee array.
I have also tried with the following code:
foreach($mutipleAssignee as $subKey => $subArray){
if($subArray['accountId'] == $this->getUsersHashMapValue($responsiblePartyIds[0])){
unset($mutipleAssignee[$subKey]);
}
}
But it is resulting as
Array
(
[tags] => Array
(
[0] => hello
)
[assignee] => 60b6a8a38cf91900695dd46b
[multiple_assignee] => Array
(
[1] => Array
(
[accountId] => 5b39d23d32e26a2de15f174f
)
)
)
rather than
[multiple_assignee] => Array
(
[0] => Array
(
[accountId] => 5b39d23d32e26a2de15f174f
)
)
Thank you
Just extract the accountId column and search that. Then use that key:
$key = array_search($this->getUsersHashMapValue($responsiblePartyIds[0]),
array_column($mutipleAssignee, 'accountId'));
unset($mutipleAssignee[$key]);
After your edit it seems you just want to reindex the subarray after unset:
$mutipleAssignee = array_values($mutipleAssignee);
I would just use a simple for loop. All of the array_* functions are really helpful but I find that they hide nuances. Since I don't have your functions I'm just making a plain-old one, but you should be able to port this.
$data = [
'tags' => [
'hello',
],
'assignee' => '60b6a8a38cf91900695dd46b',
'multiple_assignee' => [
[
'accountId' => '60b6a8a38cf91900695dd46b',
],
[
'accountId' => '5b39d23d32e26a2de15f174f',
],
],
];
$assignee = $data['assignee'];
foreach ($data['multiple_assignee'] as $multiple_assignee_key => $multiple_assignee) {
// if the root assignee is also listed in the multiple assignee area
if ($multiple_assignee['accountId'] === $assignee) {
// remove the duplicate from the multiple area
unset($data['multiple_assignee'][$multiple_assignee_key]);
// re-index the array
$data['multiple_assignee'] = array_values($data['multiple_assignee']);
}
}
This outputs:
array(3) {
["tags"]=>
array(1) {
[0]=>
string(5) "hello"
}
["assignee"]=>
string(24) "60b6a8a38cf91900695dd46b"
["multiple_assignee"]=>
array(1) {
[0]=>
array(1) {
["accountId"]=>
string(24) "5b39d23d32e26a2de15f174f"
}
}
}
Demo here: https://3v4l.org/tYppK

Enhancing asort by order of keys

I am using asort to sort the numeric array. For e.g.
$arr = [0,1,1,2,1,2,2,3];
After running asort I am getting:
Array
(
[0] => 0
[4] => 1
[2] => 1
[1] => 1
[6] => 2
[3] => 2
[5] => 2
[7] => 3
)
But I am expecting to get it in this order:
Array
(
[0] => 0
[1] => 1
[2] => 1
[4] => 1
[3] => 2
[5] => 2
[6] => 2
[7] => 3
)
See the difference in order of the keys above.
First sort the array.
Then generate an array by flipping in a way so that the keys can be separated according to values. Sort the arrays with keys and merge them to an array. And the combine the keys with the sorted values.
$arr = [0,1,1,2,1,2,2,3];
asort($arr);
$sorted = $arr;
$flipped = $new_keys = array();
foreach($arr as $key => $val) {
$flipped[$val][] = $key; // Get the keys
}
foreach($flipped as $key => $val_array) {
asort($val_array); // Sort the keys
$new_keys = array_merge($new_keys, $val_array);
}
$final = array_combine($new_keys, $sorted); // Combine them again
var_dump($final);
Output
array(8) {
[0]=>
int(0)
[1]=>
int(1)
[2]=>
int(1)
[4]=>
int(1)
[3]=>
int(2)
[5]=>
int(2)
[6]=>
int(2)
[7]=>
int(3)
}
This should work for you:
First walk through each array value with array_walk() and change each value to an array containing the value and the key.
After this use uasort() to sort your array and if both values are the same you use the key to choose which one should be first.
At the end just use array_column() to transform your array back.
<?php
$arr = [0,1,1,2,1,2,2,3];
array_walk($arr, function(&$v, $k){
$v = ["value" => $v, "key" => $k];
});
uasort($arr, function($a, $b){
if($a["value"] == $b["value"]) {
if($a["key"] == $b["key"])
return 0;
return $a["key"] > $b["key"] ? 1 : -1;
}
return $a["value"] > $b["value"] ? 1 : -1;
});
$arr = array_column($arr, "value", "key");
print_r($arr);
?>
output:
Array
(
[0] => 0
[1] => 1
[2] => 1
[4] => 1
[3] => 2
[5] => 2
[6] => 2
[7] => 3
)

Multidimensional array update

I am trying to update each language as a multidimensional array to another multidimensional array but it seems to be only saving the last key e.g.(lang_3) but not lang_1 & lang_2. Cracking my head to figure this out. Hope someone can point out my faults. ($country_specs = list of language, $get_code = country code)
$awards = array(
'award_year' => sanitize_array_text_field($_POST['award_year']),
'award_title_user' => sanitize_array_text_field($_POST['award_title_user']),
'award_description_user' => sanitize_array_text_field($_POST['award_description_user'])
);
foreach ($country_specs as $specs => $value) {
if ($value[0] == $get_code ) {
foreach ($value['lang'] as $lang_key => $lang) {
$awards_title = 'award_title_'.$lang_key;
$awards_description = 'award_description_'.$lang_key;
$awards_lang = array(
$awards_title => sanitize_array_text_field($_POST[$awards_title]),
$awards_description => sanitize_array_text_field($_POST[$awards_description])
);
update_user_meta($user_id, 'awards', array_merge($awards,$awards_lang));
}
}
}
Current code output example:
Array (
[award_year] => Array (
[0] => 1999-01
[1] => 2010-02 )
[award_title_user] => Array (
[0] => 2
[1] => tt )
[award_description_user] => Array (
[0] => 2
[1] => ddd )
[award_title_lang3] => Array (
[0] => 2CC
[1] => zz )
[award_description_lang3] => Array (
[0] => 2CCCCCCC
[1] => dzz ) )
Working code as follows.
$awards = array(
'award_year' => sanitize_array_text_field($_POST['award_year']),
'award_title_user' => sanitize_array_text_field($_POST['award_title_user']),
'award_description_user' => sanitize_array_text_field($_POST['award_description_user'])
);
$awards_new_lang = array();
foreach ($country_specs as $specs => $value) {
if ($value[0] == $get_code ) {
foreach ($value['lang'] as $lang_key => $lang) {
$awards_title = 'award_title_'.$lang_key;
$awards_description = 'award_description_'.$lang_key;
$awards_new_lang[$awards_title] = sanitize_array_text_field($_POST[$awards_title]);
$awards_new_lang[$awards_description] = sanitize_array_text_field($_POST[$awards_description]);
}
}
}
$array_merge_new = array_merge($awards, $awards_new_lang);
update_user_meta($user_id, 'awards', $array_merge_new);
I created a new array ($awards_new_lang) and did an array merge with the old array, thus combining both of the arrays together.
Try this code, it outputs as expected, I tried the mimic the variables structures
<?php
$awards = array(
'award_year' => '1999',
'award_title_user' => '2',
'award_description_user' => '2CCCCCCC'
);
$value = array();
$value['lang'] = array(1, 2, 3);
foreach ($value['lang'] as $lang_key) {
$awards_title = 'award_title_'.$lang_key;
$awards_description = 'award_description_'.$lang_key;
$awards_lang = array(
$awards_title => "$lang_key title",
$awards_description => "$lang_key desc"
);
//array merge returns an array, we save the changes here to use them later when the loops are through
$awards = array_merge($awards,$awards_lang);
}
echo '<pre>';
//Final updated version of the array
var_dump($awards);
echo '</pre>';
?>
Outputs:
array(9) {
["award_year"]=>
string(4) "1999"
["award_title_user"]=>
string(1) "2"
["award_description_user"]=>
string(8) "2CCCCCCC"
["award_title_1"]=>
string(7) "1 title"
["award_description_1"]=>
string(6) "1 desc"
["award_title_2"]=>
string(7) "2 title"
["award_description_2"]=>
string(6) "2 desc"
["award_title_3"]=>
string(7) "3 title"
["award_description_3"]=>
string(6) "3 desc"
}

how to get value from associative array

This is my array :
Array
(
[0] => Array
(
[0] => S No.
[1] => Contact Message
[2] => Name
[3] => Contact Number
[4] => Email ID
)
[1] => Array
(
[0] => 1
[1] => I am interested in your property. Please get in touch with me.
[2] => lopa <br/>(Individual)
[3] => 1234567890
[4] => loperea.ray#Gmail.com
)
[2] => Array
(
[0] => 2
[1] => This user is looking for 3 BHK Multistorey Apartment for Sale in Sohna, Gurgaon and has viewed your contact details.
[2] => shiva <br/>(Individual)
[3] => 2135467890
[4] => sauron82#yahoo.co.in
)
)
How can I retrieve all data element wise?
You can get information about arrays in PHP on the official PHP doc page
You can access arrays using square braces surrounding the key you like to select [key].
So $array[1] will give yoo:
Array
(
[0] => 1
[1] => I am interested in your property. Please get in touch with me.
[2] => lopa <br/>(Individual)
[3] => 1234567890
[4] => loperea.ray#Gmail.com
)
And $array[1][2] will give you:
lopa <br/>(Individual)
Or you can walkt through the elements of an array using loops like the foreach or the for loop.
// perfect for assoc arrays
foreach($array as $key => $element) {
var_dump($key, $element);
}
// alternative for arrays with seamless numeric keys
$elementsCount = count($array);
for($i = 0; $i < $elementsCount; ++$i) {
var_dump($array[$i]);
}
You have integer indexed elements in multidimensional array. To access single element from array, use array name and it's index $myArray[1]. To get inner element of that previous selected array, use second set of [index] - $myArray[1][5] and so on.
To dynamically get all elements from array, use nested foreach loop:
foreach ($myArray as $key => $values) {
foreach ($values as $innerKey => $value) {
echo $value;
// OR
echo $myArray[$key][$innerKey];
}
}
The solution is to use array_reduce:
$header = array_map(
function() { return []; },
array_flip( array_shift( $array ) )
); // headers
array_reduce( $array , function ($carry, $item) {
$i = 0;
foreach( $carry as $k => $v ) {
$carry[$k][] = $item[$i++];
}
return $carry;
}, $header );
First of all we get the header from the very first element of input array. Then we map-reduce the input.
That gives:
$array = [['A', 'B', 'C'], ['a1', 'b1', 'c1'], ['a2', 'b2', 'c2'], ['a3', 'b3', 'c3']];
/*
array(3) {
'A' =>
array(3) {
[0] =>
string(2) "a1"
[1] =>
string(2) "a2"
[2] =>
string(2) "a3"
}
'B' =>
array(3) {
[0] =>
string(2) "b1"
[1] =>
string(2) "b2"
[2] =>
string(2) "b3"
}
'C' =>
array(3) {
[0] =>
string(2) "c1"
[1] =>
string(2) "c2"
[2] =>
string(2) "c3"
}
}
*/
I think this is what you are looking for
$array = Array
(
0=> Array
(
0 => 'S No.',
1 => 'Contact Message',
2 => 'Name',
3 => 'Contact Number',
4 => 'Email ID'
),
1 => Array
(
0 => 1,
1 => 'I am interested in your property. Please get in touch with me.',
2 => 'lopa <br/>(Individual)',
3 => '1234567890',
4 => 'loperea.ray#Gmail.com',
),
2 => Array
(
0 => 2,
1 => 'This user is looking for 3 BHK Multistorey Apartment for Sale in Sohna, Gurgaon and has viewed your contact details.',
2 => 'shiva <br/>(Individual)',
3 => '2135467890',
4 => 'sauron82#yahoo.co.in',
)
);
$result_array = array();
array_shift($array);
reset($array);
foreach($array as $x=>$array2){
foreach($array2 as $i => $arr){
if($i == 1){
$result_array[$x]['Contact Message'] = $arr;
}elseif($i == 2){
$result_array[$x]['Name'] = $arr;
}elseif($i == 3){
$result_array[$x]['Contact Number'] =$arr;
}elseif($i == 4){
$result_array[$x]['Email ID'] = $arr;
}
}
}
print_r($result_array);

multi-dimensional array, move into a simple array

I have an array that looks like this,
[0] => Array
(
[youtube_showreel_url_1] => youtube1.com
[youtube_showreel_description] => youtube1.com - desc
)
[1] => Array
(
[youtube_showreel_url_2] => youtube2.com
[youtube_showreel_description] => youtub2.com - desc
)
[2] => Array
(
[youtube_showreel_url_3] => youtube3.com
[youtube_showreel_description] => youtube3.com - desc
)
[3] => Array
(
[youtube_showreel_url_4] => youtube4.com
[youtube_showreel_description] => youtube4.com - desc
)
[4] => Array
(
[youtube_showreel_url_5] => youtube5.com
[youtube_showreel_description] => youtube5.com - desc
)
Is it possible with PHP to turn it into something that looks like this?
[0] => Array (
[youtube_showreel_url_1] => youtube1.com
[youtube_showreel_description] => youtube1.com - desc
[youtube_showreel_url_2] => youtube2.com
[youtube_showreel_description] => youtub2.com - desc
[youtube_showreel_url_3] => youtube3.com
[youtube_showreel_description] => youtube3.com - desc
[youtube_showreel_url_4] => youtube4.com
[youtube_showreel_description] => youtube4.com - desc
[youtube_showreel_url_5] => youtube5.com
[youtube_showreel_description] => youtube5.com - desc
)
Can explode it or run it through a loop or something?
Assuming your original data is held in a variable called $input:
// This will hold the result
$result = array();
foreach ($input as $index => $item) { // Loop outer array
foreach ($item as $key => $val) { // Loop inner items
$result[$key] = $val; // Create entry in $result
}
}
// Show the result
print_r($result);
However, your input has the same key appearing in it more than once, and the later values will overwrite the first one. So you might want to do something like this:
foreach ($input as $index => $item) { // Loop outer array
foreach ($item as $key => $val) { // Loop inner items
$result[$key.$index] = $val; // Create entry in $result
}
}
<?php
$aNonFlat = array(
1,
2,
array(
3,
4,
5,
array(
6,
7
),
8,
9,
),
10,
11
);
$objTmp = (object) array('aFlat' => array());
array_walk_recursive($aNonFlat, create_function('&$v, $k, &$t', '$t->aFlat[] = $v;'), $objTmp);
var_dump($objTmp->aFlat);
/*
array(11) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
[5]=>
int(6)
[6]=>
int(7)
[7]=>
int(8)
[8]=>
int(9)
[9]=>
int(10)
[10]=>
int(11)
}
*/
?>
source : http://ca.php.net/manual/fr/function.array-values.php#86784
array keys have to have unique names meaning that you wouldn't be able to have multiple youtube_showreel_description keys or else you just overwrite the value. You could rename the key to something like youtube_showreel_description_NN where NN is the number of the description similar to how you have the url.
there would be a collision on "youtube_showreel_description"
you should think of a better data structure for that
I would suggest you retain its multidimensional array structure
Array
(
[0] => Array
(
[url] => youtube1.com
[description] => youtube1.com - desc
)
[1] => Array
(
[url] => youtube2.com
[description] => youtube2.com - desc
)
[2] => Array
(
[url] => youtube3.com
[description] => youtube3.com - desc
)
[3] => Array
(
[url] => youtube1.com
[description] => youtube3.com - desc
)
[4] => Array
(
[url] => youtube1.com
[description] => youtube4.com - desc
)
)
If you like it that way, I think its cleaner, and easier to parse
Not exactly, the [youtube_showreel_description] would overwrite itself after each declaration, you would need to use a unique identifier for each key. If the keys are not important you can just loop through your existing array with a foreach loop and set a regular iterative key and "know" that the array comes in sets where the first element is the url and the second is the description.
Edit: If the keys aren't important, you could use the url as your key and description as your value, this will make it easier to iterate over as each element pertains to only one item.
As everyone has already mentioned, you're going to get a collision on 'youtube_showreel_description'. How about something like this?:
// values (stays the same - no need to reformat)
$values = array(
array(
'youtube_showreel_url_1' => 'youtube1.com',
'youtube_showreel_description' => 'youtube1.com desc'
),
array(
'youtube_showreel_url_2' => 'youtube2.com',
'youtube_showreel_description' => 'youtube2.com desc'
),
array(
'youtube_showreel_url_3' => 'youtube3.com',
'youtube_showreel_description' => 'youtube3.com desc'
),
array(
'youtube_showreel_url_4' => 'youtube4.com',
'youtube_showreel_description' => 'youtube4.com desc'
)
);
// the good stuff
$result = array_map(function($v) {
return array(
'url' => array_shift($v),
'description' => $v['youtube_showreel_description']
);
}, $values);
// result
array(4) {
[0]=>
array(2) {
["url"] => string(12) "youtube1.com"
["description"] => string(17) "youtube1.com desc"
}
[1]=>
array(2) {
["url"] => string(12) "youtube2.com"
["description"] => string(17) "youtube2.com desc"
}
[2]=>
array(2) {
["url"] => string(12) "youtube3.com"
["description"] => string(17) "youtube3.com desc"
}
[3]=>
array(2) {
["url"] => string(12) "youtube4.com"
["description"] => string(17) "youtube4.com desc"
}
}

Categories