Efficiently transforming Arrays (PHP) - 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.

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

PHP Array rearrange numeric key as parrent key

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.

PHP - while creating array (mysql_fetch_array) program creating array in array

I want to create array:
$branza_query = mysql_query ('SELECT craft FROM base') or die...
$craft = array();
while ($cra = mysql_fetch_array($craft_query))
{
$craft[] = $cra;
}
No big deal but when i want to print_r it, i have restult like:
Array ( [0] => Array ( [0] => steel [craft] => steel )
[1] => Array ( [0] => farm [craft] => farm )
[2] => Array ( [0] => some [craft] => some )
[3] => Array ( [0] => it [craft] => it ) // etc.
)
I just wanted to add next value to existing array with result like:
Array ( [0] = steel
[1] = farm
[2] = some
[3] = it /etc.
)
or
Array ( [0] = craft => steel
[1] = craft => farm
[2] = craft => some
[3] = craft => it /etc.
)
or something similar because next thing what i want to do is something like:
foreach($craft as $value)
{
echo '<option value ="'.$value.'"> '.$value.'</option>';
}
The Problem is you create an array take $cra as its first element every time you call $craft[]=$cra, and then add it to $craft. That is why you have a three layer array as result.
But actually, $cra is already an array. So what you need to do is just array_push($craft, $cra);. Or use array_push($craft, $cra[0]); this will give what you want.
Please refer to the page http://php.net/manual/en/function.mysql-fetch-array.php

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'];
}
}

PHP array_push() - pushing new data to array

I have an array which looks like this:
Array
(
[0] => Array
(
[1] => Array
(
[name] => vrij
// ...
)
[2] => Array
(
[name] => zat
// ...
)
)
)
I build this array using a for loop; however, I need to push 4 more 'records' to the array, which I can't do in this for loop.
I want the array to look like this, after the pushes:
Array
(
[0] => Array
(
[1] => Array
(
[name] => vrij
// ...
)
[2] => Array
(
[name] => zat
// ...
)
// ...
)
[1] => Array
(
[1] => Array
(
[name] => zon
//...
)
[2] // etc
)
)
The four new records should be pushed to array[1], so I get something like
$array[1][0], $array[1][1], etc. 0 1 2 3 contains the new data.
I tried quite a lot of stuff, to be honest. I need to do four of these pushes, so I was trying a for loop:
for($i = 0; $i < 4; $i++)
{
$day_info = $this->get_day_info($i, $data['init']['next_month'], $data['init']['current_year']);
$push['name'] = $day_info['day_name'];
array_push($data['dates'], $push);
}
and all other kinds of things with [], [1][$i], etc. Sometimes it even adds five arrays! I'm confused as to why it won't just add the [1][1], [1][2],.. I'm probably missing out on something here. Thanks a lot.
If this isn't clear, please do tell and I'll add more code to explain the problem better.
$extradates = array(1 => 'zon', 2 => 'maa');
$data['dates'][] = $extradates;
Will add 2 extra dates to the array using a new index.
Although if I see what you trying to accomplish, I think there might be a better way.
This above works though :)

Categories