PHP Group array by values - php

I have an array like this:
Array (
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
[4] => ing_2_ing
[5] => ing_2_amount
[6] => ing_2_det
[7] => ing_2_meas
)
And I want to group the values into an array like this:
Array (
[0] => Array(
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
)
[1] => Array(
[0] => ing_2_ing
[1] => ing_2_amount
[2] => ing_2_det
[3] => ing_2_meas
)
)
There may be many other items named like that: ing_NUMBER_type
How do I group the first array to the way I want it? I tried this, but for some reason, strpos() sometimes fails:
$i = 1;
foreach ($firstArray as $t) {
if (strpos($t, (string)$i)) {
$secondArray[--$i][] = $t;
} else {
$i++;
}
}
What is wrong? Can you advice?

It depends what you are trying to achieve, if you want to split array by chunks use array_chunk method and if you are trying to create multidimensional array based on number you can use sscanf method in your loop to parse values:
$result = array();
foreach ($firstArray as $value)
{
$n = sscanf($value, 'ing_%d_%s', $id, $string);
if ($n > 1)
{
$result[$id][] = $value;
}
}

<?php
$ary1 = array("ing_1_ing","ing_1_amount","ing_1_det","ing_1_meas","ing_2_ing","ing_2_amount","ing_2_det","ing_2_meas");
foreach($ary1 as $val)
{
$parts = explode("_",$val);
$ary2[$parts[1]][]=$val;
}
?>
This creates:
Array
(
[1] => Array
(
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
)
[2] => Array
(
[0] => ing_2_ing
[1] => ing_2_amount
[2] => ing_2_det
[3] => ing_2_meas
)
)

What I'd do is something like this:
$result = array();
foreach ($firstArray as $value)
{
preg_match('/^ing_(\d+)_/', $value, $matches);
$number = $matches[1];
if (!array_key_exists($number, $result))
$result[$number] = array();
$result[$number][] = $value;
}
Basically you iterate through your first array, see what number is there, and put it in the right location in your final array.
EDIT. If you know you'll always have the numbers start from 1, you can replace $number = $matches[1]; for $number = $matches[1] - 1;, this way you'll get exactly the same result you posted as your example.

Related

php - rearranging an array into groups

I have an array of filenames:
Array
(
[2] => 1_1_page2-img1.jpg
[3] => 1_2_page2-img1-big.jpg
[4] => 2_1_page2-img1.jpg
[5] => 2_2_page2-img1-big.jpg
[6] => 3_1_page2-img1.jpg
[7] => 4_1_page2-img1.jpg
[8] => 4_2_page2-img1.jpg
[9] => 5_2_page2-img1.jpg
)
I'm trying to rearrange them so they're grouped together by their first number. I'm guessing I could maybe separate them with a pipe so I could then distinguish them afterwards. Either that or a multidimensional array.
I know I can perform an explode("_",$filename); to get the first and second digits before the underscores.
The catch is even though the beginning numbers should always increment, there won't necessarily be 2 files per initial number.
So I'm either trying to make it into the following:
Array
(
[0] => 1_1_page2-img1.jpg|1_2_page2-img1-big.jpg
[1] => 2_1_page2-img1.jpg|2_2_page2-img1-big.jpg
[2] => 3_1_page2-img1.jpg|
[3] => 4_1_page2-img1.jpg|4_2_page2-img1.jpg
[4] => |5_2_page2-img1.jpg
)
Or something a bit tidier perhaps? I just can't work out the foreach to put them together.
Or is there an array related command that will put them together easier?
My preference would be to store them in subarrays, as this will be much easier to deal with in the long run; so this would be a possibility, given your array is in $arr:
$newarr = array ();
while (list($key, $val) = each($arr)) {
$subarray_index = substr($val, 0, strpos($val, "_"));
$newarr[$subarray_index][] = $val;
}
Is this what you mean?
$arr = Array(
2 => '1_1_page2-img1.jpg',
3 => '1_2_page2-img1-big.jpg',
4 => '2_1_page2-img1.jpg',
5 => '2_2_page2-img1-big.jpg',
6 => '3_1_page2-img1.jpg',
7 => '4_1_page2-img1.jpg',
8 => '4_2_page2-img1.jpg',
9 => '5_2_page2-img1.jpg'
);
function orderArray($pArr){
$first = '0';
$newArr = array();
foreach($pArr as $val){
if(strpos($val,$first) !== 0){
if(substr($val,2,1)==='1'){
$newArr[]=$val;
}else{
$newArr[]='|'.$val;
}
$first = substr($val,0,1);
}else{
$curIndex = count($newArr) - 1;
$newArr[$curIndex] = $newArr[$curIndex].'|'.$val;
}
return $newArr;
}
$result = orderArray($arr);
print "number of values: ".count($result)."<br>";
foreach($result as $value){
print $value."<br>";
}
Just worked it out now based on another post in stackoverflow:
foreach ($scanned_directory as $filename){
$ids = explode("_",$filename);
$groups[$ids[0]][] = $filename;
}
echo "<pre>";
ksort($groups);
print_r($groups);
echo "</pre>";
Displays:
Array
(
[1] => Array
(
[0] => 1_1_page2-img1.jpg
[1] => 1_2_page2-img1-big.jpg
)
[2] => Array
(
[0] => 2_1_page2-img1.jpg
[1] => 2_2_page2-img1-big.jpg
)
[3] => Array
(
[0] => 3_1_page2-img1.jpg
[1] => 3_2_page2-img1-big.jpg
)
[10] => Array
(
[0] => 10_1_page2-img1.jpg
)
[11] => Array
(
[0] => 11_2_page2-img1-big.jpg
)
)
There isn't a nice automated way of doing this, but you could use a simple loop:
$array = [];
foreach ($filename as $file) {
$fields = explode('_', $file);
$array[$fields[0]][$fields[1]] = $file;
}
An example is located here.

PHP: Parsing data within multidimensional array

I have an array which looks like this:
Array
(
[0] => Array
(
[0] => TE=140414100000 cd =AB1234 ggg =1234567 gbh =2
[7] => nd: DA1AAAAAAAAAA: TD = 140414:
)
[1] => Array
(
[0] => TE=140414100000 cd =AB1234 ggg =1234567 ghb =2
[7] => nd: DA1AAAAAAAAAA: TD = 140414:
)
)
what I am trying to acomplish is to parse data within each sub array and create a new multidimensional array with the parsed data.
Example: the data in parentheses below is what should be returned in new multidimensional array
Array
(
[0] => Array
(
[0] => te=(140414100000) cd =AB(1234) ggg =1234567 ghb =2
[7] => nd: DA(1)(AAAAAAAAAA): TD = (140414):
)
[1] => Array
(
[0] => te=(140414100000) cd =AB(1234) ggg =1234567 ghb =2
[7] => nd: DA(2)(BBBBBBBBBB): TD = (140414):
)
)
What I want to return:
Array
(
[0] => Array
(
[0] => 140414100000
[1] => 1234
[2] => 1
[3] => AAAAAAAAAA
[4] => 140414
)
[1] => Array
(
[0] => 140414100000
[1] => 1234
[2] => 2
[3] => BBBBBBBBBB
[4] => 140414
)
).
So my question is what would be the best way to acomplish this?
This is what I have come up with. It works, however is seems very inefficient as it adds a lot of empty arrays which have to be cleaned up.
foreach($new as $key => $val){
foreach($val as $res){
preg_match_all('%te=([0-9]{12})\s%',$res,$matches);
$out[$key][] = $matches[1][0];
preg_match_all('%cd\s+=AB([0-9]{4})%',$res,$matches);
$out[$key][] = $matches[1][0];
preg_match_all('%nd:\sDA([0-9]{1})%',$res,$matches);
$out[$key]['node'] = $matches[1][0];
preg_match_all('%nd:\sDA[0-9]{1}([a-zA-Z]{10,14}):%',$res,$matches);
$out[$key]['rset'] = $matches[1][0];
preg_match_all('%td\s=\s([0-9]{6}):%',$res,$matches);
$out[$key]['trdt'] = $matches[1][0];
}
}
foreach($out as $v){
$v = array_values(array_filter($v));
$return[] = $v;
}
return $return;
Thanks in advance.
UPDATED:
This worked and is much more efficient. Thanks for the example Shankar
foreach($new as $key => $val){
$v = implode('', $val);
preg_match_all("%te=([0-9]{12})|cd\s+=AB([0-9]{4})|nd:\sDA([0-9]{1})|([A-Z]{3,7}):|td=\s([0-9]{6}):%",$v,$matches);
$new_array[$key]['time'] = $matches[1][0];
$new_array[$key]['code'] = $matches[2][1];
$new_array[$key]['sp'] = $matches[3][2];
$new_array[$key]['rset'] = $matches[4][3];
$new_array[$key]['trfdt'] = $matches[5][4];
}
echo "<pre>";
print_r($new_array);
echo "</pre>";
Loop through your array and implode each array element and use a preg_match_all() to capture all the entries bewteen ( and ) and then pass those matches to your new array.
foreach($arr as $k=>$arr1)
{
$v = implode('',$arr1);
preg_match_all('^\((.*?)\)^', $v, $matches);
$new_arr[]=$matches[1];
}
print_r($new_arr);
Working Demo

PHP: array_splice() not giving me correct output

I'm trying to experiment with array_splice and I get an output like this (from $match)
Array
(
[Keep me Updated] => Array
(
[winner] => winnerl.jpg
[0] => value0.jpg
)
[0] => valuel.jpg //this should really be inside [Leep me Updated] array
[1] => value2.jpg //this should really be inside [Leep me Updated] array
[2] => value3.jpg //this should really be inside [Leep me Updated] array
}
from (this foreach creates puts in the values into $match)
foreach($data as $d)
{
if (isset($match[$d['data']['name']])) {
$match_loser = array($d['loser']['lrg_img']);
array_splice($match,1,0,$match_loser);
}else{
$match[$d['data']['name']] = array("winner"=>$d['winner']['lrg_img'],
$d['loser']['lrg_img']);
}
}
What I'm trying to get is bring [0],[1],[2] into the [Keep me Updated] $match array:
Array
(
[Keep me Updated] => Array
(
[winner] => winnerl.jpg
[0] => value0.jpg
[1] => value1.jpg // old one: [0] => valuel.jpg
[2] => value2.jpg // old one: [1] => value2.jpg
[3] => value3.jpg // old one: [2] => value3.jpg
)
}
This is what $data looks like
$data[] = array(
"data"=>array
(
"name"=>$name,
),
"winner"=>array
(
"lrg_img"=>$img_url_winner
),
"loser"=>array
(
"lrg_img"=>$img_url_loser
)
$data has array values, and $match is where I'm trying to sort the data. So if my values match, it'll consolidate.
Thanks!
Use the inner array as the argument to array_splice
foreach($data as $d)
{
if (isset($match[$d['data']['name']])) {
$match_loser = array($d['loser']['lrg_img']);
array_splice($match[$d['data']['name']],1,0,$match_loser);
}else{
$match[$d['data']['name']] = array("winner"=>$d['winner']['lrg_img'],
$d['loser']['lrg_img']);
}
}

Convert complex numerical array to associative array

I have an array data that look like this :
Array (
[0] => Array (
[0] => Name:
[1] => John W.
[2] => Registration ID:
[3] => 36
)
[1] => Array (
[0] =>Age:
[1] => 35
[2] => Height:
[3] => 5'11"
)
[3] => Array (
[0] => Sex:
[1] => M
[2] => Weight:
[3] => 200lbs
)
[4] => Array (
[0] => Address
)
[5] => Array (
[0] => 6824 crestwood dr delphi, IN 46923
))
And I want to convert it to associative array like this :
Array(
['Name']=> John W.
['Registration ID']=> 36
['Age']=> 35
['Height'] => 5'11''
['Sex']=>M
['Weight']=>200lbs
['Address']=>6824 crestwood dr delphi, IN 46923
)
I have no idea at all how to do this, since the supposed to be array column header were also in sequence, so it makes difficult to convert this array.
Any help I appreciate, thx.
Given your origin array is called $origin , you can do it like this:
$merged = array();
foreach($origin as $val) {
$merged = array_merge($merged, $val);
}
$tot = count($merged) - 1;
for ($i=0;$i<$tot;$i+=2) {
$result[$merged[$i]] = $merged[$i+1];
}
var_dump($result); // To test the resulting array
Firstly, I use array_merge() to flatten the $origin array to only one dimension/depth, so we later iterate it (stepping each 2 items per iteration) and assigning each pair of items ($i and $i+1) to the resulting array.
Looks like, for the first 3 children, you can just assign the even value to the previous element as key. Then, assign the fourth one as key for fifth element.
$result = array();
foreach ($array as $key => $value)
{
if ($key < 4) {
$elements = array_values($value);
$result[$elements[0]] = $elements[1];
$result[$elements[2]] = $elements[3];
}
if ($key == 4)
$fifthkey = $value;
if ($key == 5)
$result[$fifthkey] = $value;
}
Also, note that you have to escape your height string quotes.

How can I create multidimensional arrays from a string in PHP?

So My problem is:
I want to create nested array from string as reference.
My String is "res[0]['links'][0]"
So I want to create array $res['0']['links']['0']
I tried:
$result = "res[0]['links'][0]";
$$result = array("id"=>'1',"class"=>'3');
$result = "res[0]['links'][1]";
$$result = array("id"=>'3',"class"=>'9');
when print_r($res)
I see:
<b>Notice</b>: Undefined variable: res in <b>/home/fanbase/domains/fanbase.sportbase.pl/public_html/index.php</b> on line <b>45</b>
I need to see:
Array
(
[0] => Array
(
[links] => Array
(
[0] => Array
(
[id] => 1
[class] => 3
)
)
)
[1] => Array
(
[links] => Array
(
[0] => Array
(
[id] => 3
[class] => 9
)
)
)
)
Thanks for any help.
So you have a description of an array structure, and something to fill it with. That's doable with something like:
function array_create(&$target, $desc, $fill) {
preg_match_all("/[^\[\]']+/", $desc, $uu);
// unoptimized, always uses strings
foreach ($uu[0] as $sub) {
if (! isset($target[$sub])) {
$target[$sub] = array();
}
$target = & $target[$sub];
}
$target = $fill;
}
array_create( $res, "[0]['links'][0]", array("id"=>'1',"class"=>'3') );
array_create( $res, "[0]['links'][1]", array("id"=>'3',"class"=>'9') );
Note how the array name itself is not part of the structure descriptor. But you could theoretically keep it. Instead call the array_create() function with a $tmp variable, and afterwards extract() it to achieve the desired effect:
array_create($tmp, "res[0][links][0]", array(1,2,3,4,5));
extract($tmp);
Another lazy solution would be to use str_parse after a loop combining the array description with the data array as URL-encoded string.
I have a very stupid way for this, you can try this :-)
Suppose your string is "res[0]['links'][0]" first append $ in this and then put in eval command and it will really rock you. Follow the following example
$tmp = '$'.'res[0]['links'][0]'.'= array()';
eval($tmp);
Now you can use your array $res
100% work around and :-)
`
$res = array();
$res[0]['links'][0] = array("id"=>'1',"class"=>'3');
$res[0]['links'][0] = array("id"=>'3',"class"=>'9');
print_r($res);
but read the comments first and learn about arrays first.
In addition to mario's answer, I used another function from php.net comments, together, to make input array (output from jquery form serializeArray) like this:
[2] => Array
(
[name] => apple[color]
[value] => red
)
[3] => Array
(
[name] => appleSeeds[27][genome]
[value] => 201
)
[4] => Array
(
[name] => appleSeeds[27][age]
[value] => 2 weeks
)
[5] => Array
(
[name] => apple[age]
[value] => 3 weeks
)
[6] => Array
(
[name] => appleSeeds[29][genome]
[value] => 103
)
[7] => Array
(
[name] => appleSeeds[29][age]
[value] => 2.2 weeks
)
into
Array
(
[apple] => Array
(
[color] => red
[age] => 3 weeks
)
[appleSeeds] => Array
(
[27] => Array
(
[genome] => 201
[age] => 2 weeks
)
[29] => Array
(
[genome] => 103
[age] => 2.2 weeks
)
)
)
This allowed to maintain numeric keys, without incremental appending of array_merge. So, I used sequence like this:
function MergeArrays($Arr1, $Arr2) {
foreach($Arr2 as $key => $Value) {
if(array_key_exists($key, $Arr1) && is_array($Value)) {
$Arr1[$key] = MergeArrays($Arr1[$key], $Arr2[$key]);
}
else { $Arr1[$key] = $Value; }
}
return $Arr1;
}
function array_create(&$target, $desc, $fill) {
preg_match_all("/[^\[\]']+/", $desc, $uu);
foreach ($uu[0] as $sub) {
if (! isset($target[$sub])) {
$target[$sub] = array();
}
$target = & $target[$sub];
}
$target = $fill;
}
$input = $_POST['formData'];
$result = array();
foreach ($input as $k => $v) {
$sub = array();
array_create($sub, $v['name'], $v['value']);
$result = MergeArrays($result, $sub);
}

Categories