PHP : Add lowest value from duplicate records of array - php

I want to remove duplicate record which is highest value in array.
Array :
Array
(
[0] => Array
(
[id] => 1
[number] => 123
[price] => 6
)
[1] => Array
(
[id] => 2
[number] => 456
[price] => 6
)
[2] => Array
(
[id] => 3
[number] => 123
[price] => 5
)
)
Expected Result :
Array
(
[0] => Array
(
[id] => 2
[number] => 456
[price] => 6
)
[1] => Array
(
[id] => 3
[number] => 123
[price] => 5
)
)
number is duplicate field and after that need to compare price. Which will be lower that will be display. Rest of all should be removed.
What I tried :
$lowest = min($myArray);
$result = array_filter($myArray, function($value, $key) use ($lowest) {
return $value === $lowest;
}, ARRAY_FILTER_USE_BOTH);
How can i do that?
UPDATE :
#Daniel Dez solution is almost working. I used 3rd solution of him. But, It should be working like this.
For ex : number 123 is duplicate records now it's lowest price is 2. Then, it should be display rest of 123 number's array element remove.
Array :
$data = [
[
"id" => 1,
"number" => 123,
"price" => 2,
],
[
"id" => 2,
"number" => 456,
"price" => 6,
],
[
"id" => 3,
"number" => 123,
"price" => 5,
],
[
"id" => 4,
"number" => 123,
"price" => 11,
],
[
"id" => 5,
"number" => 456,
"price" => 5,
],
[
"id" => 6,
"number" => 123,
"price" => 5,
]
];
Expected Output :
Array
(
[0] => Array
(
[id] => 1
[number] => 123
[price] => 2
)
[1] => Array
(
[id] => 2
[number] => 456
[price] => 5
)
)
please help me.
Thanks.

Data:
$numbers = array_unique(array_column($data, 'number'));
usort($data, function ($a, $b) {
return $a['price'] - $b['price'];
});
$result = [];
foreach ($numbers as $number) {
foreach ($data as $item) {
if ($item['number'] == $number) {
break;
}
}
$result[] = $item;
}
print_r($result);

Related

How to Remove value from an array using another array with multiple values?

I have two array Array1 and Array2 and I need to remove Array2 value from Array1 I show my both the Array here.
In Array1 I have utype_id is 11 and 14 and I need to remove this id record from Array2 so how can I do it can you please help me?
Array1(
[0] => stdClass Object
(
[id] => 22
[accessid] => 2
[utype_id] => 11
[discount] => 3434
[published] => 1
)
[1] => stdClass Object
(
[id] => 23
[accessid] => 2
[utype_id] => 14
[discount] => 2
[published] => 1
)
)
Array2
(
[0] => stdClass Object
(
[id] => 9
[type_name] => Admin
[description] => admin
[published] => 0
)
[1] => stdClass Object
(
[id] => 10
[type_name] => Senior sales
[description] => senior sales
[published] => 0
)
[2] => stdClass Object
(
[id] => 11
[type_name] => junior sales
[description] => junior
[published] => 1
)
[3] => stdClass Object
(
[id] => 14
[type_name] => dealer
[description] => dealer
[published] => 0
)
[4] => stdClass Object
(
[id] => 15
[type_name] => fgdg
[description] => dfg
[published] => 1
)
[5] => stdClass Object
(
[id] => 16
[type_name] => fgdfg
[description] => fgdfg
[published] => 0
)
)
I didn't get any solution for this. I need only 9,10,15,16 Record id from Array2.
Just for entertainment purposes (and I was feeling a bit left out :( ). Index both arrays by the ID (need php 7+ for array_column() to support objects as input) and then array_diff_key() to remove any from the second array...
print_r(array_diff_key(array_column($array2, null, "id"),
array_column($array1, null, "utype_id")));
I would like to say that a foreach() solution is faster than this, just wanted to join in and post some original content.
First, extract utype_ids from first array, make them keys to speed up search:
$utype_ids = [];
foreach ($array1 as $item) {
$utype_ids[$item->utype_id] = 1;
}
Then, filter second array using $utype_ids:
$filtered_array = array_filter(
$array2,
function($v) use ($utype_ids) {
return !isset($utype_ids[$v->id]);
}
);
Demo: https://3v4l.org/i2heV
Use nested loops to perform the qualifying checks. Use a break as a matter of best practice to avoid unnecessary iterations.
Code: (Demo)
$blacklist = [
(object)["id" => 22,"accessid" => 2, "utype_id" => 11, "discount" => 3434, "published" => 1],
(object)["id" => 23,"accessid" => 2, "utype_id" => 14, "discount" => 2, "published" => 1]
];
$rows = [
(object)["id" => 9, "type_name" => "Admin", "description" => "admin", "published" => 0],
(object)["id" => 10, "type_name" => "Senior sales", "description" => "senior sales", "published" => 0],
(object)["id" => 11, "type_name" => "junior sales", "description" => "junior sales", "published" => 1],
(object)["id" => 14, "type_name" => "dealer", "description" => "dealer", "published" => 0],
(object)["id" => 15, "type_name" => "fgdg", "description" => "dfg", "published" => 1],
(object)["id" => 16, "type_name" => "fgdfg", "description" => "fgdfg", "published" => 0]
];
foreach ($blacklist as $disqualifier) { // iterate the blacklist
foreach ($rows as $index => $row) { // iterate the list to be checked
if ($row->id === $disqualifier->utype_id) { // if row should be disqualified
unset($rows[$index]); // remove the row
break; // stop checking the $rows for this $disqualifier
}
}
}
var_export($rows);
...if you need the output to be reindexed, you can call array_values($rows).
If these arrays of objects are coming from a database table, you should be improving your query to do this filtration process in advance.
You can use..
$arr1ids = array();
foreach($array1 as $val1){
$arr1ids[] = $val1->utype_id;
}
$resArr = array();
foreach($array2 as $val2){
if(!in_array($val2->utype_id,$arr1ids)){
$resArr[] = $val2;
}
}
print_r($resArr);

PHP Merge arrays and add a value

I need help merging two PHP arrays:
Array 1:
Array
(
[0] => 2
[1] => 3
[2] => 4
[3] => 6
)
Array 2:
Array
(
[0] => Array
(
[id_sabor] => 2
[chocolate] => N
)
[1] => Array
(
[id_sabor] => 3
[chocolate] => S
)
[2] => Array
(
[id_sabor] => 4
[chocolate] => N
)
[3] => Array
(
[id_sabor] => 5
[chocolate] => S
)
[4] => Array
(
[id_sabor] => 6
[chocolate] => N
)
)
The values on array 1 are the active objects. I need to keep on Array 2 or on a new array only the ones with an [id_sabor] that matches in the array 1 (in this case: 2, 3, 4 and 6). Also, on those that [chocolate]=S add a new value: [costo_extra]=25.
One way to do that could be to use array_reduce and use in_array to check if the first array contains the value of id_sabor.
$array1 = [2, 3, 4, 6];
$array2 = [
["id_sabor" => 1, "chocolate" => "N"],
["id_sabor" => 2, "chocolate" => "N"],
["id_sabor" => 3, "chocolate" => "S"],
["id_sabor" => 4, "chocolate" => "N"],
["id_sabor" => 5, "chocolate" => "S"],
["id_sabor" => 6, "chocolate" => "N"]
];
$array2 = array_reduce($array2, function($carry, $item) use ($array1){
if (in_array($item["id_sabor"], $array1)) {
if ($item["chocolate"] === "S") {
$item["costo_extra"] = 25;
}
$carry[] = $item;
}
return $carry;
});
Demo

In php is there a function like array_column for multidimensional arrays [duplicate]

This question already has answers here:
How to group subarrays by a column value?
(20 answers)
Closed 2 years ago.
Is there function that works similar to array_column for multidimensional arrays? Is there a function that translates the first array below to the second:
Array
(
[0] => Array
(
[foodType] => fruits
[itemID] => 1
[itemName] => apple
)
[1] => Array
(
[foodType] => fruits
[itemID] => 2
[itemName] => banana
)
[2] => Array
(
[foodType] => veggies
[itemID] => 3
[itemName] => carrot
)
[3] => Array
(
[foodType] => veggies
[itemID] => 4
[itemName] => broccoli
)
)
Resulting array:
Array
(
[fruits] => Array
(
[0] => Array
(
[itemID] => 1
[itemName] => apple
)
[1] => Array
(
[itemID] => 2
[itemName] => banana
)
)
[veggies] => Array
(
[0] => Array
(
[itemID] => 3
[itemName] => carrot
)
[1] => Array
(
[itemID] => 4
[itemName] => broccoli
)
)
)
No, there is not a function to get your expected output natively, though you can make your own functions, just use array_column to get the types/column, and then loop over your array, on match remove the item as to not duplicate iterations.
Something like:
<?php
$data = [
['foodType' => 'fruits', 'itemID' => 1, 'itemName' => 'apple'],
['foodType' => 'fruits', 'itemID' => 2, 'itemName' => 'banana'],
['foodType' => 'veggies', 'itemID' => 3, 'itemName' => 'carrot'],
['foodType' => 'veggies', 'itemID' => 4, 'itemName' => 'broccoli']
];
function array_column_multi ($array, $column) {
$types = array_unique(array_column($array, $column));
$return = [];
foreach ($types as $type) {
foreach ($array as $key => $value) {
if ($type === $value[$column]) {
unset($value[$column]);
$return[$type][] = $value;
unset($array[$key]);
}
}
}
return $return;
}
print_r(array_column_multi($data, 'foodType'));
https://3v4l.org/KQVeN
Result:
Array
(
[fruits] => Array
(
[0] => Array
(
[itemID] => 1
[itemName] => apple
)
[1] => Array
(
[itemID] => 2
[itemName] => banana
)
)
[veggies] => Array
(
[0] => Array
(
[itemID] => 3
[itemName] => carrot
)
[1] => Array
(
[itemID] => 4
[itemName] => broccoli
)
)
)
Oh I just noticed that you're aggregating them by ID. There's not a function for that, you're going to need to iterate over the input with a loop, and populate an output array with the data you want. Eg:
$output = [];
foreach($input_array as $item) {
$output[$item['id']][] = [
'itemID' => $item['itemID'],
'itemName' => $item['itemName']
];
}
Quite old question, but I hope it help someone. Unfortunately there's no native function yet but output is achievable using php's array_filter():
$foods = [
[
'foodType' => 'fruits',
'itemID' => 1,
'itemName' => 'apple',
],
[
'foodType' => 'fruits',
'itemID' => 2,
'itemName' => 'banana',
],
[
'foodType' => 'veggies',
'itemID' => 3,
'itemName' => 'carrot',
],
[
'foodType' => 'veggies',
'itemID' => 4,
'itemName' => 'broccoli',
]
];
$grouped_foods = [];
$groupByColumn = 'foodType';
array_filter($foods, function ($foodItem) use(&$grouped_foods, $groupByColumn) {
$grouped_foods[$foodItem[$groupByColumn]][] = array_filter($foodItem, function ($key) use($groupByColumn) {
return $key != $groupByColumn;
}, ARRAY_FILTER_USE_KEY);
});
echo "<pre>";
print_R($grouped_foods);
echo "</pre>";
see in action: https://3v4l.org/bbX5A
Disclaimer: for/foreach loops are significantly faster in performance than native array functions.
I prefer using the following solution.
Example
"allergens" => array:5 [
0 => array:2 [
"id" => "10"
"object" => array:1 [
"allergens" => "10"
]
]
1 => array:2 [
"id" => "11"
"object" => array:1 [
"allergens" => "11"
]
]
2 => array:2 [
"id" => "4"
"object" => array:1 [
"allergens" => "4"
]
]
]
Giving this example, if you would like an array containing only the value of allergens then use the following code.
Solution
$allergens = array_map( function ( $ar ) {
return $ar['allergens'];
}, array_column( $allergensArr, 'object' ) );
Result
array:5 [
0 => "10"
1 => "11"
2 => "4"
]

Filter php array based on other array with different elements [duplicate]

This question already has answers here:
While comparing associative rows between two 2d arrays, array_diff_assoc() gives the wrong difference
(3 answers)
Closed 4 months ago.
I have an array $items as such:
[0] => Array (
[itemid] => 8
[name] => A
[rating] => 9.5
)
[1] => Array (
[itemid] => 41
[name] => B
[rating] => 9.5
)
and another array $array as such:
[0] => Array (
[itemid] => 458
[name] => C
[rating] => 9.603
)
[1] => Array (
[itemid] => 460
[name] => D
[rating] => 9.603
)
[2] => Array (
[itemid] => 8
[name] => A
[rating] => 9.523
)
[3] => Array (
[itemid] => 41
[name] => B
[rating] => 9.2
)
What I would like to do is return the array $array, but with all the elements from $items filtered out. In this case it would return $array, but without [2] and [3].
I've tried with array_diff(), but the rating can change from one array to the other, so the elements in the one array are not always the same as in the other array.
How do I go about this?
Is this what you're looking for?
<?php
$arr1 = [];
$arr1[] = [ "itemid" => 8, "name" => "A", "rating" => 9.5 ];
$arr1[] = [ "itemid" => 41, "name" => "B", "rating" => 9.5 ];
$arr2 = [];
$arr2[] = [ "itemid" => 458, "name" => "C", "rating" => 9.603 ];
$arr2[] = [ "itemid" => 460, "name" => "D", "rating" => 9.603 ];
$arr2[] = [ "itemid" => 8, "name" => "A", "rating" => 9.523 ];
$arr2[] = [ "itemid" => 41, "name" => "B", "rating" => 9.2 ];
function compare_by_itemid($a, $b) {
return $a['itemid'] - $b['itemid'];
}
var_dump(array_udiff($arr2,$arr1,'compare_by_itemid'));
You could first get the item ID values as keys of an $exclude associative array (like a set), and then iterate $array to perform the filter:
$exclude = array_column($items, "itemid", "itemid"); // create set
foreach($array as $row) {
if (!isset($exclude[$row["itemid"]])) $result[] = $row;
}
The $result will have entries with item IDs that do not occur in $items.

Make array unique in multidimensional array php codeigniter

I have this array
Array (
[0] => Array
(
[0] => stdClass Object
(
[id] => 226
[user_id] => 1
[name] => Eden Corner Tub by Glass - $2099
)
[1] => stdClass Object
(
[id] => 225
[user_id] => 1
[name] => Blue Quilted Leather Jacket by Minusey - $499
)
[2] => stdClass Object
(
[id] => 222
[user_id] => 1
[name] => Darling New Bathtub by Duravit - $6300
)
)
[1] => Array
(
[0] => stdClass Object
(
[id] => 226
[user_id] => 1
[name] => Eden Corner Tub by Glass - $2099
)
[1] => stdClass Object
(
[id] => 229
[user_id] => 1
[name] => Batman Tumbler Golf Cart - $50000
)
[2] => stdClass Object
(
[id] => 228
[user_id] => 1
[name] => Swirlio Frozen Fruit Dessert Maker - $60
)
) )
I have an array of products that I need to make sure are unique.
Need to make this array unique by id. These array are generated by pushing value.
I'm trying to solve this for more than a week now, but I dont get it to work. I know it should be easy...but anyway - I don't get it :D
Try this:
$array = array(
0 => array(
"name" => "test",
"id" => 4
),
1 => array(
"name" => "test2",
"id" => 152
),
2 => array(
"name" => "test2",
"id" => 152
)
);
$newArray = array();
foreach($array as $value) {
$newArray[$value['id']]['name'] = $value['name'];
$newArray[$value['id']]['id'] = $value['id'];
}
foreach($array as $key=>$inner_array)
{
foreach($array as $key_again=>$array_again)
{
if($key != $key_again)
{
if($inner_array['name'] != $array_again['name'] AND $inner_array['id'] != $array_again['id'])
{
//its okay
}
else
{
unset($array[$key]);
}
}
}
}
Not sure how the arrays are generated, but, if you can change that, you could set the array keys to the IDs directly and check if the id is already set.
Otherwise, you can do the following:
$unique = array();
foreach( $array as $values ) {
if( ! isset( $unique[$values['id']] ) ) {
$unique[$values['id']] = $values;
}
}
This will make your array unique:
$array = array(
0 => array(
"name" => "test",
"id" => 4
),
1 => array(
"name" => "test2",
"id" => 152
),
2 => array(
"name" => "test2",
"id" => 152
) );
$result = array();
$index = array();
foreach($array as $i => $elem) {
if(!isset($index[$elem['id']])) {
$result[$i] = $elem;
$index[$elem['id']] = 1;
}
}
echo var_export($result);
Output:
array (
0 =>
array (
'name' => 'test',
'id' => 4,
),
1 =>
array (
'name' => 'test2',
'id' => 152,
),
)
This will work. It could be considered more clean than a for loop, but I'm not sure about performance.
$array = [
[ "name" => "test", "id" => 4 ],
[ "name" => "test2", "id" => 152 ],
[ "name" => "test2", "id" => 152 ]
];
array_walk($array, function(&$item, $idx) use($array){
$matches = array_slice(array_keys($array, $item), 1);
if (in_array($idx, $matches)) {
$item = false;
}
});
$array = array_filter($array);
Edit Since you updated the data set to work with, you would need to flatten it 1 level:
$array = call_user_func_array('array_merge', $array);

Categories