combining arrays in php - php

Lets say I want to combine 2 arrays and the arrays are names $year_into and $likes_dislikes. They share a key called "name". How can I make it so that this one:
$year_info
Array
(
[0] => Array
(
[name] => JOE MONROE
[year] => 1950
[info] => his ghost still haunts us
)
[1] => Array
(
[name] => FUTUREMAN
[year] => 1930
[info] => RIP
)
)
and this one $likes_dislikes
Array
(
[0] => Array
(
[name] => JOE MONROE
[likes] => cornbread
[dislikes] => pain
)
[1] => Array
(
[name] => E. Case
[likes] => chaos
[dislikes] => order
)
[2] => Array
(
[name] => FUTUREMAN
[likes] => mustard
[dislikes] => mayo
)
)
Can be combined into one array $complete that looks like this, where the information from the 2nd array is added to the 1st if the "name" value matches:
Array
(
[0] => Array
(
[name] => JOE MONROE
[year] => 1950
[info] => his ghost still haunts us
[likes] => cornbread
[dislikes] => pain
)
[1] => Array
(
[name] => FUTUREMAN
[year] => 1930
[info] => RIP
[likes] => mustard
[dislikes] => mayo
)
)
I've looked through the already asked questions but don't see anything, maybe I'm using the wrong terminology to describe the problem. I'm stuck on the foreach loop because if I say like this
foreach ($year_info as $y){
$complete[]=array('name'=>$y['name'], 'year'=>$y['year'], 'info'=>$y['info'], 'likes'=$likes_dislikes[0]['likes'],'dislikes'=>$likes_dislikes[0]['dislikes'] )
}
I'll just get the same values for likes/dislikes for all. What is the simplest way to do this?

Here's a crazy one-liner (I guess it technically counts as one line), that should work.
$complete = array_map(function($a) use($likes_dislikes){
foreach($likes_dislikes as $ld){
if($a['name'] === $ld['name']){
return $a + $ld;
break;
}
}
}, $year_info);
This will only work in PHP 5.3+, otherwise you can do it like this:
$complete = array();
foreach($year_info as $a){
foreach($likes_dislikes as $ld){
if($a['name'] === $ld['name']){
$complete[] = $a + $ld;
break;
}
}
}

What I would try to do is loop through both sets of arrays (a nested foreach loop would be a good choice), checking for instances where The name attribute is the same in both arrays. When they are, you can use array_merge() to merge them into a new array. An example would be:
$newArray = array();
foreach ($arr1 as $first) {
foreach ($arr2 as $second) {
if($first["name"] == $second["name"]){
array_push($newArray, array_merge($first, $second));
}
}
}
Assuming you named your arrays $arr1 and $arr2.

The super-lazy, extra-expository approach:
$complete = array();
foreach($year_info as $yr){
$name = $yr['name'];
foreach($likes_dislikes as $ld){
if($ld['name']!=$name){
continue;
}else{
$new_entity = array();
$new_entity['name'] = $name;
$new_entity['year'] = $yr['year'];
$new_entity['info'] = $yr['info'];
$new_entity['likes'] = $ld['likes'];
$new_entity['dislikes'] = $ld['dislikes'];
$complete[] = $new_entity;
break;
}
}
}
Though this will perform poorly with large arrays, it would make more sense to change the data structure if possible. It would be better to have data structures that were simply keyed by name. Do you have control over your input?

just loop over both arrays to create a third one.
$complete = array();
foreach ($year_info as $year) {
foreach ($like_dislikes as $like {
if ($year['name'] == $like['name']) {
$complete[] = array_merge($year, $like);
}
}
}

Related

PHP 2 arrays using one to chose from the other

I am new to php and my problem is i have 2 arrays the first one is from another page via post and read into an array via post_get
Array (
[0] => 93
[1] => 25
[2] => 5
[3] => 4
[4] => 36
)
and my second array looks like this
Array (
[25] => Estonia
[20] => France
[4] => Germany
[5] => Greece
[75] => Hungary
[93] => India
[36] => Italy
)
what i want to do is if the array looks like the first one then it uses the numbers from the array and with the help from the second array makes a new array that only contains
Array (
[0] => India
[1] => Estonia
[2] => Greece
[3] => Germany
[4] => Italy
)
and using this doesn't work
$group is the first array
$array is the one with the country names
foreach ($group as $value) {
if (in_array($value, $array)) {
}
else {
echo "The group ".$value." does not exist";
}
}
You can do this many ways. Here is a simple one:
$new = [];
foreach ($group as $groupId) {
if (isset($array[$groupId])) {
$new[] = $array[$groupId];
}
}
I would do it like this. Flip $group and find the key intersection with $array:
$result = array_intersect_key($array, array_flip($group));
That will retain the keys, so if you want to re-index:
$result = array_values(array_intersect_key($array2, array_flip($array1)));
No need to use in_array just add some if checking and two foreach loops and use the key of the first array to the index of the second one.
Idea:
$array3 = array();
foreach($array1 as $key) {
if(isset($array2[$key])) { // add some checking just so make sure no undefined indices
$array3[] = $array2[$key];
}
}
Another alternative solution using array_map function:
$result = array_map(function($v) use($array){
return isset($array[$v])? $array[$v] : $v;
}, $group);

accessing specific elements of arrays in a foreach loop

I apologize if this is a very simple question - I've read through tons of posts here, but my question is syntactically very hard to search for, so I haven't found an answer yet.
I have a json array that's output from a company's API:
[Result] => Array
(
[cData] => Array
(
[0] => Array
(
[Reqa] => ABCD
[Reqb] =>
[Reqc] => Plus
[dto] => Array
(
[0] => Array
(
[ComID] => 43292392
[Comment] => Dave
)
[1] => Array
(
[ComID] => 43292392
[Comment] => Bob
)
)
[XREFSearchOperation] => Exact
)
[1] => Array
(
[Reqa] => BCDE
[Reqb] =>
[Reqc] => A
[dto] => Array
(
[0] => Array
(
[ComID] => 19331186
[Comment] => Mike
)
[1] => Array
(
[ComID] => 19331186
[Comment] => Roger
)
)
[XREFSearchOperation] => Starts With
)
[2] => Array
(
[Reqa] => QQDT
[Reqb] =>
)
)
)
)
and I'm trying to access the [ComID] and [Comment] elements, if they exist, inside of a foreach loop and assign it to the variable $y
So far I have:
foreach ($json['Result']['cData']['dto'] as $i) {
$y = "{$i['ComID']}|{$i['Comment']}";
}
but this gives me zero results. I understand WHY, because in between ['cData'] and ['dto'] are [0], [1], [2] etc.. elements, and I don't know how to add a qualifier for those into the loop.
Update
This code works for most of the json response:
foreach ($json['Result']['cData'] as $i) {
if(array_key_exists('dto', $i)) {
foreach ($i['dto'] as $j) {
$y = "{$j['ComID']}|{$j['Comment']}";
} else {
}
}
However - I'm having one more small issue. If there are multiple [dto] responses, you'll have [dto][0][ComID] then [dto][1][ComID] and [dto][2][ComID], (like in the example above,) but if there's only ONE response, you'll have [dto][ComID] as there's no need for that middle array.
I tried writing if(array_key_exists('dto[0]' to execute one, then an else statement in the event dto[0] doesn't exist, but that didn't work. I need a way of NOT executing a foreach loop if there is no array underneath it to "foreachicize". Is there an if/else statement I can write to accommodate this?
Probably need a nested foreach:
foreach ($json['Result']['cData'] as $i) {
foreach($i['dto'] as $j) {
$y[] = "{$j['ComID']}|{$j['Comment']}"; //need an array here
}
}
For the update to the question. Check if $i['dto'][0] exists:
foreach ($json['Result']['cData'] as $i) {
if(isset($i['dto'][0]))) {
foreach($i['dto'] as $j) {
$y[] = "{$j['ComID']}|{$j['Comment']}";
}
} else {
$y[] = "{$j['ComID']}|{$j['Comment']}";
}
}
There might be a better way but I'm headed out.
Another approach:
foreach($json['Result']['cData'] as $cData)
{
foreach($cData['dto'] as $dto)
{
if(array_key_exists('ComID', $dto) && array_key_exists('Comment', $dto))
{
$y = "{$dto['ComID']}|{$dto['Comment']}";
}
}
}

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.

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

php - recreate array?

I've "inherited" some data, which I'm trying to clean up. The array is from a database which, apparently, had no keys.
The array itself, is pretty long, so I'm simplifying things for this post...
[0] => Array
(
[id] => 2
[uid] => 130
[eid] => 8
[ename] => Standard
[eaction] => Check
)
[1] => Array
(
[id] => 2
[uid] => 110
[eid] => 8
[ename] => Standard
[eaction] => Check
)
[2] => Array
(
[id] => 2
[uid] => 200
[eid] => 8
[ename] => Standard
[eaction] => Check
)
I'm trying to shift things around so the array is multidimensional and is grouped by ename:
[0] => Array
(
[Standard] => Array
(
[id] => 2
[uid] => 130
[eid] => 8
[eaction] => Check
)
)
[0] => Array
(
[Standard] => Array
(
[id] => 2
[uid] => 130
[eid] => 8
[eaction] => Check
)
)
[0] => Array
(
[Standard] => Array
(
[id] => 2
[uid] => 130
[eid] => 8
[eaction] => Check
)
)
Anyone know how to do something like this?
You can use usort() to sort an array by a user-defined function. That function could compare the ename fields. Then it's just a simple transformation. Like:
usort($array, 'cmp_ename');
function cmp_ename($a, $b) {
return strcmp($a['ename'], $b['ename']);
}
and then:
$output = array();
foreach ($array as $v) {
$ename = $v['ename'];
unset($v['ename']);
$output[] = array($ename => $v);
}
$outputarray = array();
foreach($inputarray as $value) {
$outputarray[] = array($value['ename'] => $value);
}
would accomplish what your examples seem to indicate (aside from the fact that your 'result' example has multiple things all with key 0... which isn't valid. I'm assuming you meant to number them 0,1,2 et cetera). However, I have to wonder what benefit you're getting from this, since all it appears to be doing is adding another dimension that serves no purpose. Perhaps you could clarify your example if there are other things to take into account?
$outputarray = array();
foreach($inputarray as &$value) {
$outputarray[][$value['ename']] = $value;
unset($value['ename']);
} unset($value);
I'm guessing that this is what you're asking for:
function array_group_by($input, $field) {
$out = array();
foreach ($input as $row) {
if (!isset($out[$row[$field]])) {
$out[$row[$field]] = array();
}
$out[$row[$field]][] = $row;
}
return $out;
}
And usage:
var_dump(array_group_by($input, 'ename'));
philfreo was right but he was also off a little. with his code every time you encounter an array element with an ['ename'] the same as one you've already gone through it will overwrite the data from the previous element with the same ['ename']
you might want to do something like this:
$output = array();
foreach ($YOURARRAY as $value) {
$output[$value['ename']][] = $value;
}
var_dump($output); // to check out what you get

Categories