PHP Array rearrange numeric key as parrent key - php

i want to rearrange a simple multidimensional array.
Array
(
[pieces] => Array
(
[0] => 2
[1] => 9
)
[start] => Array
(
[0] => 0001
[1] => 9901
)
[end] => Array
(
[0] => 0002
[1] => 9909
)
[group] => Array
(
[0] => 0001-0100
[1] => 9901-9999
)
)
to
Array
(
[tokens] => Array
(
[0] => Array
(
[start] => 0001
[end] => 0002
[pieces] => 2
[group] => 0100
)
[1] => Array
(
[start] => 9901
[end] => 9909
[pieces] => 9
[group] => 9901-9999
)
)
)
I have tried something similar this:
$keys = array_keys($array);
foreach ($keys as $key => $val) {
foreach ($array as $k => $v){
foreach($array[$v] as $tk => $tv){
if($val == $k){
$new['tokens'][][$val] = $tv;
}
}
}
}
The numeric is the set of tokens which i prosted from my form,
Please can anyone explain me what i do wrong?
I am working some hours with different codes (i know the solution is very simple) but I am a little bit confused :/
Thank you very much!
BR KK

The Fourth Bird's solution is quite rigid in that it:
Requires an explicitly-defined key in the loop condition.
Enforces that the entire result has no more items than that one key has.
Assumes and enforces that the input keys are sequential and zero-indexed.
The below will work no matter what:
foreach( $array as $y => $inner ) {
foreach( $inner as $x => $value ) {
$new['tokens'][$x][$y] = $value;
}
}
Demo: https://3v4l.org/Rmdtd
Edit: I think it's worth preserving The Fourth Bird's explanation of the trouble with the posted code from his now-deleted answer:
You are trying to index into $array[$v], but $v in the case is one
of the sub arrays. According to the array
docs:
Arrays and objects can not be used as keys. Doing so will result in
a warning: Illegal offset type.
Make sure that you have error_reporting turned up to E_ALL while you're developing code so that you can see non-critical messages that indicate current and/or future problems.

Related

Replace values in associative array

I'm consuming an API which returns an array of objects as this:
$base = array(
["orange","_","banana"],
["banana","_","_"],
["_","apple","kiwi"],
["_","raspberry","strawberry"]
);
And I intend to show "0" when key value is "_" however I haven't found a better way to do this than this:
foreach ($base as $key => $value) {
for ($i=0; $i<=3;$i++) {
if ($base[$key][$i]=="_")
$base[$key][$i]="0";
}
}
This works just fine since it's a simple demo but the real array is sometimes big and I've found this solution somewhat inefficient.
My question is, there's some php built-in function to do achieve this in or at least a better way to do this?
Thanks in advance guys,
Use array_walk_recursive(), pass the elements by reference and walk over the array, checking for the value _ - if its a match, replace it with 0.
$base = array(
["orange","_","banana"],
["banana","_","_"],
["_","apple","kiwi"],
["_","raspberry","strawberry"]
);
array_walk_recursive($base, function(&$v) {
if ($v === '_')
$v = 0;
});
Output becomes
Array
(
[0] => Array
(
[0] => orange
[1] => 0
[2] => banana
)
[1] => Array
(
[0] => banana
[1] => 0
[2] => 0
)
[2] => Array
(
[0] => 0
[1] => apple
[2] => kiwi
)
[3] => Array
(
[0] => 0
[1] => raspberry
[2] => strawberry
)
)
Live demo at https://3v4l.org/6Bs8ZE
You can replace _ with 0;
json_decode(str_replace('"_"','"0"',json_encode($base)));

merging array in CI 3

I want to merge two arrays in order to get the data as per my requirement.
I am posting my result, please have a look.
First array:
Array
(
[0] => Array
(
[km_range] => 300
[id] => 2
[car_id] => 14782
)
[1] => Array
(
[km_range] => 100
[id] => 3
[car_id] => 14781
)
[2] => Array
(
[km_range] => 300
[id] => 4
[car_id] => 14783
)
)
Second array:
Array
(
[0] => Array
(
[user_id] => 9c2e00508cb28eeb1023ef774b122e86
[car_id] => 14783
[status] => favourite
)
)
I want to merge the second array into the first one, where the value at key car_id matches the equivalent value; otherwise it will return that field as null.
Required output:
<pre>Array
(
[0] => Array
(
[km_range] => 300
[id] => 2
[car_id] => 14782
)
[1] => Array
(
[km_range] => 100
[id] => 3
[car_id] => 14781
)
[2] => Array
(
[km_range] => 300
[id] => 4
[car_id] => 14783
[fav_status] => favourite
)
)
Since the merge is so specific I would try something like this:
foreach ($array1 as $index => $a1):
foreach ($array2 as $a2):
if ($a1['car_id'] == $a2['car_id']):
if ($a2['status'] == "favourite"):
$array1[$index]['fav_status'] = "favourite";
endif;
endif;
endforeach;
endforeach;
You might be able to optimize the code more but this should be very easy to follow...
Another way to achieve this without using the index syntax is to reference the array elements in the foreach by-reference by prepending the ampersand operator:
foreach($firstArray as &$nestedArray1) {
foreach($secondArray as $nestedArray2) {
if ($nestedArray1['car_id'] == $nestedArray2['car_id']) {
$nestedArray1['fav_status'] = $nestedArray2['status'];
}
}
}
You can see it in action in this Playground example.
Technically you asked about merging the arrays. While the keys would be different between the input arrays and the desired output (i.e. "status" vs "fav_status"), array_merge() can be used to merge the arrays.
if ($nestedArray1['car_id'] == $nestedArray2['car_id']) {
$nestedArray1 = array_merge($nestedArray1, $nestedArray2);
}
Playground example.
Additionally the union operators (i.e. +, +=) can be used.
If you want to append array elements from the second array to the first array while not overwriting the elements from the first array and not re-indexing, use the + array union operator1
if ($nestedArray1['car_id'] == $nestedArray2['car_id']) {
$nestedArray1 += nestedArray1;
}
Playground example.
1http://php.net/manual/en/function.array-merge.php#example-5587

Iterate through multidimensional PHP array and output values

I'm having a real headache trying to iterate through an array and output elements. Using the array structure below I want to be able to output each instance of partname.
The following loop outputs the first instance of partname. I can't seem to adapt it to loop through all instances within the array. I'm sure I'm missing something basic.
foreach($ItemsArray['assignments'] as $item) {
$partname = $item['grades'][0]['partname'];
}
Array
(
[assignments] => Array
(
[0] => Array
(
[assigntmentid] => 5101
[grades] => Array
(
[0] => Array
(
[id] => 5101
[name] => Advanced AutoCad
[partid] => 6601
[partname] => Draft
[userid] => 82069
[grade] => 53
[courseid] => 6265
[fullname] => Computer Aided Design
)
)
)
[1] => Array
(
[assigntmentid] => 5101
[grades] => Array
(
[0] => Array
(
[id] => 5101
[name] => Advanced AutoCad
[partid] => 6602
[partname] => Final
[userid] => 82069
[grade] => 35
[courseid] => 6265
[fullname] => Computer Aided Design
)
)
)
)
)
Instead of just coding by slapping the keyboard. Write down what your function needs to do. In english (or whatever language you prefer). This would be something like:
Foreach assignment, loop over all grades and store the partname of
that grade into an array.
And then code it:
function getPartnames($assignments) {
$partNames = array();
foreach ($assignments as $assignment) {
foreach($assignment['grades'] as $grade) {
$partNames[] = $grade['partname'];
}
}
return $partNames;
}
So what did I do? I simply translated english to code.
Some few more tips: Use variables names that make sense. $item; $ItemArray; ... don't make sense. They tell me nothing
use an extra foreach in your loop:
foreach($ItemsArray['assignments'] as $item) {
foreach($item['grades'] as $grade) {
echo $grade['partname'];
}
}

Efficiently transforming Arrays (PHP)

Edit: Thanks to #Felix Kling and #mario for pointing me towards named capture groups and PREG_SET_ORDER, I totally learned something today.
I'm curious about a better algorithm per se, though. So please just pretend that there's no preg_match() involved.
Edit 2: Abstracted question
While answering another question here, I stumbled upon the fact that my code for turning
this:
Array
(
[0] => Array (
[0] => 1
[1] => 3
)
[1] => Array (
[0] => Description text
[1] => Different Description text
)
[2] => Array (
[0] => 123.456.12
[1] => 234.567.89
)
[3] => Array (
[0] => 10.00
[1] => 10.00
)
[4] => Array (
[0] => 10.00
[1] => 30.00
)
)
into that:
Array
(
[0] => Array
(
[qty] => 1
[description] => "Description text"
[sku] => 123.456.12
[price] => 10.00
[total] => 10.00
)
…
)
is fugly:
$field_names = array('qty', 'description', 'sku', 'price', 'total');
$result_arr = array();
$num_iter = count(matches[0]);
for ($i = 0; $i < $num_iter; $i++) {
foreach ($field_names as $index => $field_name) {
$result_arr[$i][$field_name] = array_shift($input_arr[$index]);
}
}
Any suggestions for improvement?
There is one simpler way to produce the desired output.
while (count($input_arr[0])) {
$values = array_map("array_shift", & $input_arr);
$result_arr[] = array_combine($field_names, $values);
}
This won't work past PHP 5.3, as it requires forcibly passing a parameter by reference. (Avoiding any dumbing-down-the-language remarks here). But you can of course chop off the entries with a more elaborate manual loop at any time.
The real simplification for such cases is however array_combine to turn a list into an associative array.

Check Arrays with different keys?

How do i check if a specific array key exist and how to compare them?
1. Array looks like this.
[33] => Array
(
[211] =>objectr
(
[name] => Test
[id]=> 211
)
)
[23] => Array
(
[311] =>objectr
(
[name] => Tester
[id]=> 311
)
)
2. Array looks like this
[0] => 311
[1] => 211
[2] => 99
Now i need to compare them and get the id of them.
What im looking for is something like that
[0] => Tester
[1] => Test
How do i do that?
array_key_exists - http://php.net/manual/en/function.array-key-exists.php
foreach($first_array as $arr) {
foreach($second_array as $key=>$val)
{
if (array_key_exists($val, $first_array)) {
$final_array[$key] = $arr['name'];
}
}
}
or array_search - http://uk.php.net/array_search
foreach($first_array as $arr) {
foreach($second_array as $val)
{
$key = array_search($val, $arr);
if($key !== false) $final_array[$key] = $arr['name'];
}
}
In both cases you should end up with:
[0] => Tester
[1] => Test
I would transform Array 1 like removing the outer key (at least temporarily) then while iterating through Array 2, i'd compare against transformed Array 1 with array_key_exists.
I hope I understood your question, there might be a language barrier, but here we go:
so basically you have 3 arrays and you want to use the last to to check against the first one to see if those values/keys exists in the first? Well the firs thing you want to do is re structure your first array into something that can easily be translated for checking the values and keys of the next two arrays. so lets call the first array $mapArray:
foreach($mapArray as $mapObject){
foreach($mapObject as $object){
$mapList[$object->id] = $object->name;
}
}
Now this should give us something like:
[211] => 'test'
[311] => 'tester'
So now lets call the 2nd array $arrayIds and the 3rd $arrayNames. To see if am id exists and to get its name when given the array $arrayIds, all you need to do is this:
//given [0] => 311
$keyExists = array_key_exists(311, $mapList); //returns true is the key exists
echo $mapList[311]; //returns tester, the name for the id given
And the other way around:
//given [0] => 'test'
$nameExists = in_array('test', $mapList);
if($nameExists) echo array_search('test', $mapList); // returns 211
hope this is what you are looking for or at least helps you find what you are looking for.
Another approach: We reduce the first array to one dimension:
$first = array();
foreach($first_array as $val) {
$first[key($val)] = current($val);
}
gives:
Array
(
[211] => Array
(
[name] => Test
[id] => 211
)
[311] => Array
(
[name] => Tester
[id] => 311
)
)
(I used an array instead of an object but it works the same).
and then we compute the intersection of the keys:
//assume
$second_array = array(311, 99);
$result = array_intersect_key($first, array_flip($second_array));
which gives:
Array
(
[311] => Array
(
[name] => Tester
[id] => 311
)
)
So it is not quite what you want but you can easily access the name property via $element->name.

Categories