I been getting two arrays and merging them and then looking for a certain value under name but can't seem to get it working
$temp = [
['id' => 3, 'name' => 'Taylor'],
['id' => 3, 'name' => 'Abigail'],
];
$temp1 = [
['id' => 3, 'name' => 'Taylor'],
['id' => 3, 'name' => 'Taylor'],
];
$ggg = array_merge($temp,$temp1);
Use the contains() method of a collection. The schema:
collect($array1) // Create a collection from the first array
->merge($array2) // merge it with the second array
->contains($key, $value); // returns boolean
Your code:
$temp = [
['id' => 3, 'name' => 'Taylor'],
['id' => 3, 'name' => 'Abigail'],
];
$temp1 = [
['id' => 3, 'name' => 'Taylor'],
['id' => 3, 'name' => 'Taylor'],
];
collect($temp)->merge($temp1)->contains('name', 'Taylor'); // true
collect($temp)->merge($temp1)->contains('name', 'Jane'); // false
If you want to get the items who are matching the criteria, use where():
$result = collect($temp)->merge($temp1)->where('name', 'Taylor');
This will return:
Collection {#465 ▼
#items: array:3 [▼
0 => array:2 [▼
"id" => 3
"name" => "Taylor"
]
2 => array:2 [▼
"id" => 3
"name" => "Taylor"
]
3 => array:2 [▼
"id" => 3
"name" => "Taylor"
]
]
}
Use print_r($ggg) to print the resulting array. Referring to the name part you should use $ggg[0]['name'] for example. Not sure what is your final goal for merging the 2 arrays, do you want an array with all 4 elements ? The way you are doing it you will end up with only 2 elements, index 0 of $temp1 will overwrite index 0 of $temp, same thing with index 1.
I have tried and maybe this will help you.
$temp = [
['id' => 3, 'name' => 'Taylor'],
['id' => 3, 'name' => 'Abigail'],
];
$temp1 = [
['id' => 3, 'name' => 'Taylor'],
['id' => 3, 'name' => 'Taylor'],
];
$ggg = array_merge($temp,$temp1);
foreach ($ggg as $key) {
echo "ID: ".$key['id']."<br>";
echo "NAME: ".$key['name']."<br>";
}
I think you want something like below. Since you tagged this as Laravel I've done it with laravel specific code, but it would be possible to use native PHP too.
$temp = [
['id' => 3, 'name' => 'Taylor'],
['id' => 3, 'name' => 'Abigail'],
];
$temp1 = [
['id' => 3, 'name' => 'Taylor'],
['id' => 3, 'name' => 'Taylor'],
];
$item = collect($temp)->merge($temp1)->first(function ($item) {
return $item['name'] == 'Taylor';
});
Related
I'm trying to apply custom keys to a collection in laravel.
The best way that I found was using functions like transform or mapWithKeys.
$result = $collection->map(function ($item) {
return [
'custom_key_name_1' => $item[0],
'custom_key_name_2' => $item[1],
'custom_key_name_3' => $item[2],
];
});
I was hoping to find something like:
$keys = ['custom_key_name_1', 'custom_key_name_2', 'custom_key_name_3'];
result = $collection->withKeys($keys);
Do you know any other way to do that with a less verbose code?
I'm working in a legacy Laravel 5.5 project.
Input Example
$collection = collect([
[ 'first', 'second', 'third' ],
[ '1', '2', '3' ],
[ '1st', '2nd', '3rd' ],
]);
Expected Output
[
[
'custom_key_name_1' => 'first',
'custom_key_name_2' => 'second',
'custom_key_name_3' => 'third',
],
[
'custom_key_name_1' => '1',
'custom_key_name_2' => '2',
'custom_key_name_3' => '3',
],
[
'custom_key_name_1' => '1st',
'custom_key_name_2' => '2nd',
'custom_key_name_3' => '3rd',
],
]
Since you're working with a collection of arrays, you can use PHP's array_combine() method to put the keys and values together:
$collection = collect([
[ 'first', 'second', 'third' ],
[ '1', '2', '3' ],
[ '1st', '2nd', '3rd' ],
]);
$keys = ['custom_key_name_1', 'custom_key_name_2', 'custom_key_name_3'];
$result = $collection->map(fn ($v) => array_combine($keys, $v));
dump($result);
Result:
Illuminate\Support\Collection^ {#5189
#items: array:3 [
0 => array:3 [
"custom_key_name_1" => "first"
"custom_key_name_2" => "second"
"custom_key_name_3" => "third"
]
1 => array:3 [
"custom_key_name_1" => "1"
"custom_key_name_2" => "2"
"custom_key_name_3" => "3"
]
2 => array:3 [
"custom_key_name_1" => "1st"
"custom_key_name_2" => "2nd"
"custom_key_name_3" => "3rd"
]
]
#escapeWhenCastingToString: false
}
The important caveat being that, per the documentation, "a ValueError is thrown if the number of elements in keys and values does not match."
I am using laravel.
How can I create a new array and have the properties of another.
Example the carriage array can have 3 rows that are of the "info" properties, but the brand is added.
$info = [
['id' => 1, 'color'=> 'blue'],
['id' => 2, 'color'=> 'red'],
['id' => 3, 'color'=> 'yellow'],
];
$car = [
['id' => 'id_info', 'brand'=> 'toyota', 'color' => 'color_info']
];
You can loop through array and add key to each array
$info = [
['id' => 1, 'color'=> 'blue'],
['id' => 2, 'color'=> 'red'],
['id' => 3, 'color'=> 'yellow'],
];
$newInfo = [];
foreach($info as $eachInfo){
$newInfo[] = array_merge($eachInfo,['brand' => 'toyota']);
}
dd($newInfo);
Will produce output like
array:3 [
0 => array:3 [
"id" => 1
"color" => "blue"
"brand" => "toyota"
]
1 => array:3 [
"id" => 2
"color" => "red"
"brand" => "toyota"
]
2 => array:3 [
"id" => 3
"color" => "yellow"
"brand" => "toyota"
]
]
I have N arrays. with n grade_items subarrays.
just like this.
array:2 [
0 => array:10 [
"id" => 9
"course_id" => 6
"semester_id" => 2
"name" => "Assignment"
"total_score" => 10
"grade_items" => array:1 [
0 => array:7 [
"id" => 5
"gradelist_id" => 9
"student_course_id" => 11
"score" => 8
"created_at" => "2020-04-21T03:31:20.000000Z"
"updated_at" => "2020-04-21T20:04:10.000000Z"
]
]
]
1 => array:10 [
"id" => 10
"course_id" => 6
"semester_id" => 2
"name" => "Pop Quiz"
"total_score" => 20
"grade_items" => array:1 [
0 => array:7 [
"id" => 6
"gradelist_id" => 10
"student_course_id" => 11
"score" => null
"created_at" => "2020-04-22T00:11:17.000000Z"
"updated_at" => "2020-04-22T00:11:17.000000Z"
]
]
]
]
I am trying to add each grade_item subarray from each array where the student_course_id is the same. Where there is only one grade_item and no other one with the same student_course_id, then it returns just that one value instead of a sum.
I have gone through this thread
But it just messed up the logic in my head further. I've been at this for weeks.
When I add the scores from each grade_item, i want to put that value into another model say "result_model" that would look like:
result_item [
"id" => 1,
"student_course_id" => 11,
"score" => 15 //total of grade_items from all arrays where the student_course_id's were the same
];
Help!
So basically you want to regroup the current information to receive the sum of grades. It seems the the information comes form a databases, so why don't you GROUP BY and sum on database level?
Anyway. Here's an approach. Start by keeping a map of student_course_id => score. First it will be empty: $map = [];
Then start iterating through the whole structure e.g. foreach ($data as $row. For each row, you need to check all the corresponding grade_items e.g. foreach ($row['grade_items'] as $gradeItem). Now you need to check whether the student_course_id from the grade item is present into the mapping.
If it's not present, create it with starting value of zero e.g.
if (!key_exists($gradeItem['student_course_id'], $map)) {
$map[$gradeItem['student_course_id']] = 0;
}
Once you ensure that the student_course_id is present, you can just add to the previous value the current score => $map[$gradeItem['student_course_id']] += $gradeItem['score'].
Here is a sample data i used
$array = [
[
'id' => 9,
'course_id' => 6,
'semester_id' => 2,
'name' => 'Assignment',
'total_score' => 10,
'grade_items' => [
[
'id' => 5,
'gradelist_id' => 9,
'student_course_id' => 11,
'score' => 8,
'created_at' => '2020-04-21T03:31:20.000000Z',
'updated_at' => '2020-04-21T20:04:10.000000Z',
],
[
'id' => 5,
'gradelist_id' => 9,
'student_course_id' => 15,
'score' => 15,
'created_at' => '2020-04-21T03:31:20.000000Z',
'updated_at' => '2020-04-21T20:04:10.000000Z',
]
]
],
[
'id' => 10,
'course_id' => 6,
'semester_id' => 2,
'name' => 'Pop Quiz',
'total_score' => 20,
'grade_items' => [
[
'id' => 6,
'gradelist_id' => 10,
'student_course_id' => 11,
'score' => 21,
'created_at' => '2020-04-22T00:11:17.000000Z',
'updated_at' => '2020-04-22T00:11:17.000000Z',
],
[
'id' => 6,
'gradelist_id' => 10,
'student_course_id' => 23,
'score' => 15,
'created_at' => '2020-04-22T00:11:17.000000Z',
'updated_at' => '2020-04-22T00:11:17.000000Z',
]
]
]
];
and here is the code;
$id = 0;
return collect($array)
->flatMap(function ($item){
return $item['grade_items'];
})
->groupBy('student_course_id')
->transform(function ($subItems, $courseId) use (&$id) {
$id++;
return [
'id' => $id,
'student_course_id' => $courseId,
'score' => $subItems->sum('score')
];
})
->values()
->toArray();
here is the result;
[
[
'id' => 1,
'student_course_id' => 11,
'score' => 29,
],
[
'id' => 2,
'student_course_id' => 15,
'score' => 15,
],
[
'id' => 3,
'student_course_id' => 23,
'score' => 15,
]
]
Use the sum() function. You can loop through the array, and do any checks you need, like if it is not Null etc, and pluck() it and then sum() it.
May I suggest recursivity approach?
<?php
function rec_sum_grades(&$array_grades, &$sum = 0){
$sum += $array_grades['total_score'];
if(!empty($array_grades['grade_items'])){
$this->rec_sum_grades($array_grades['grade_items'], $sum);
}
}
rec_sum_grades($array_grades, $sum);
echo $sum;
?>
I've done some research including going through PHP Sort Array By SubArray Value but this is a variation:
I have an array as follows:
$data =
[
0 => [
'id' => (int) 5,
'name' => 'Foo',
'group_id' => (int) 1,
],
1 => [
'id' => (int) 6,
'name' => 'Bar',
'group_id' => (int) 1,
],
2 => [
'id' => (int) 8,
'name' => 'Baz',
'group_id' => (int) 7,
],
3 => [
'id' => (int) 9,
'name' => 'ABC',
'group_id' => (int) 2,
],
4 => [
'id' => (int) 10,
'name' => 'DEF',
'group_id' => (int) 65,
]
];
I also have an array second array of group_id's that are relevant to a search a user has performed:
$gids = [7, 65];
What I want to do is order $data by group_id based on the values inside $gids. So the order of $data should become:
0 => [
'id' => (int) 8,
'name' => 'Baz',
'group_id' => (int) 7,
],
1 => [
'id' => (int) 10,
'name' => 'DEF',
'group_id' => (int) 65,
]
2 => [
'id' => (int) 5,
'name' => 'Foo',
'group_id' => (int) 1,
],
3 => [
'id' => (int) 6,
'name' => 'Bar',
'group_id' => (int) 1,
],
4 => [
'id' => (int) 9,
'name' => 'ABC',
'group_id' => (int) 2,
],
Note that once the $gids array has been taken into account, the group_id of the remaining items in $data is numerical (ascending order in this case: 1, 1, 2).
I understand it's possible to use usort and an anonymous function, e.g.
usort($data, function ($gids) {
});
However, I don't understand what to write inside this function to perform ordering in this way? My initial thought was to do a foreach($gids) followed by a foreach($data) and compare the group_id value. But I don't know what to do in terms of modifying $data so that it reorders.
Please can someone help?
Equally, if there is already a post which explains how to do this please let me know, because I couldn't find one on here. The original link simply bases ordering numerically, not on a second array ($gids equivalent).
Using PHP 7.1.0
This should do the trick
usort($data, function($a, $b) use ($gids)
{
$posA = array_search($a['group_id'], $gids);
if ($posA === false) {
$posA = 9999;
}
$posB = array_search($b['group_id'], $gids);
if ($posB === false) {
$posB = 9999;
}
return $posA - $posB;
});
If found in the array of $gids, the sorting of $gids will be used, else the elements will stay in the order they're given in.
The return I'm getting is the following:
array:5 [▼ 0 => array:3 [▼
"id" => 8
"name" => "Baz"
"group_id" => 7 ] 1 => array:3 [▼
"id" => 10
"name" => "DEF"
"group_id" => 65 ] 2 => array:3 [▼
"id" => 5
"name" => "Foo"
"group_id" => 1 ] 3 => array:3 [▼
"id" => 6
"name" => "Bar"
"group_id" => 1 ] 4 => array:3 [▼
"id" => 9
"name" => "ABC"
"group_id" => 2 ] ]
So I have this array in PHP.
$arr = [
[ 'sections' => [1], 'id' => 1 ],
[ 'sections' => [2], 'id' => 1 ],
[ 'sections' => [3], 'id' => NULL ],
[ 'sections' => [4], 'id' => 4 ],
[ 'sections' => [5], 'id' => 4 ],
[ 'sections' => [6], 'id' => 4 ]
];
I want to merge on 'id' and get something like
$arr = [
[ 'sections' => [1, 2], 'id' => 1 ],
[ 'sections' => [3], 'id' => NULL ],
[ 'sections' => [4, 5, 6], 'id' => 4 ]
];
Just struggling to get my head around this one. Any Ideas
I've created this quick function that might work for you
<?php
// Your array
$arr = array(
array( 'elem1' => 1, 'elem2' => 1 ),
array( 'elem1' => 2, 'elem2' => 1 ),
array( 'elem1' => 3, 'elem2' => NULL ),
array( 'elem1' => 4, 'elem2' => 4 ),
array( 'elem1' => 5, 'elem2' => 4 ),
array( 'elem1' => 6, 'elem2' => 4 )
);
print_r($arr);
function mergeBy($arr, $elem2 = 'elem2') {
$result = array();
foreach ($arr as $item) {
if (empty($result[$item[$elem2]])) {
// for new items (elem2), just add it in with index of elem2's value to start
$result[$item[$elem2]] = $item;
} else {
// for non-new items (elem2) merge any other values (elem1)
foreach ($item as $key => $val) {
if ($key != $elem2) {
// cast elem1's as arrays, just incase you were lazy like me in the declaration of the array
$result[$item[$elem2]][$key] = $result[$item[$elem2]][$key] = array_merge((array)$result[$item[$elem2]][$key],(array)$val);
}
}
}
}
// strip out the keys so that you dont have the elem2's values all over the place
return array_values($result);
}
print_r(mergeBy($arr));
?>
Hopefully it'll work for more than 2 elements, and you can choose what to sort on also....