I want to delete price index from each of the array.
Here is a sample code:
Array([0] => Array
(
[player_id] => 108
[trnmnt_team_id] => 1
[player_type] => 1
[user_team_id] => 11
[user_id] => 4
[price] => 10.00
)
[1] => Array
(
[player_id] => 151
[trnmnt_team_id] => 2
[player_type] => 1
[user_team_id] => 11
[user_id] => 4
[price] => 10.00
)
)
I tried to delete following way but it shown unexpected 'unset' (T_UNSET):
foreach ($mergeAllType as $key => $value) {
$price=$value;
$withOutPrice[]=unset($price['price']);
}
unset doesn't returns any value (it's language construct, not a function), you must do it following way:
unset($price['price']);
$withOutPrice[] = $price;
Tomas.lang's answer works fine if you know the last index's key. However if you don't know the name of the last key you could use the following:
unset(end($price));
$withOutPrice = $price;
You already got your answers regarding your foreach loop.
So, let me give you a different answer, using array_map and an anonymous function ;-)
<?php
$src = array(
array (
'player_id' => 108,
'trnmnt_team_id' => 1,
'player_type' => 1,
'user_team_id' => 11,
'user_id' => 4,
'price' => 10.00,
),
array (
'player_id' => 151,
'trnmnt_team_id' => 2,
'player_type' => 1,
'user_team_id' => 11,
'user_id' => 4,
'price' => 10.00,
),
);
$withOutPrice = array_map(
function($e) {
unset($e['price']);
return $e;
},
$src
);
var_export($withOutPrice);
If you want to unset() all off the price keys in your array you can use array_walk()
array_walk($arr, function(&$array) {
unset($array['price']);
});
Just replace $arr with whatever your arrays name is, i.e. $teams.
If you want to have two arrays, one with price and one without price you could duplicate the array before doing the above; i.e.
$teams = <DATASOURCE>
$teamsWithoutPrice = $teams;
array_walk($teamsWithoutPrice, function(&$array) {
unset($array['price']);
});
Then if you print out your $teamsWithoutPrice array you'll have your array with the price key removed.
Hope it helps.
Related
This question already has answers here:
How to access and manipulate multi-dimensional array by key names / path?
(10 answers)
Closed 1 year ago.
I'm trying to create a function that will assign new values to a specific indexes in a multidimensional array:
I Have the array that looks like this:
data[i]['checkin'];
data[i]['checkout'];
data[i]['content'][x]['price'];
data[i]['content'][x]['profit'];
data[i]['content'][x]['exchangerate'];
first parameter of my function will get the array, And second parameter will get the indexes that I want to redefine:
For example:
function defineNewValues(&$arr, $keys) {
//logic
}
Call the function:
defineNewValues($myArray, [
'data.*.content.*.price' => 0,
'data.*.content.*.profit => 0,
]);
Im beliving that recursion is the key for my problem ,
But not really know how to solve it.
Thank You.
could something like this be okay?
I only ask you to study this code not to implement it, for the simple reason that in the future you may have the same type of problem.
function setValue($key,$value,&$array){
$find_parts = explode(".", $key);
$find = $find_parts[0]??null;
if ($find!=null){
if ($find == "*"){
array_shift($find_parts);
foreach($array as &$sub_array){
setValue(implode(".",$find_parts),$value,$sub_array);
}
}else{
if (count($find_parts)>1){
if (array_key_exists($find,$array)){
array_shift($find_parts);
setValue(implode(".",$find_parts),$value,$array[$find]);
}
}else{
if (array_key_exists($find,$array)){
$array[$find] = $value;
}
}
}
}
}
function defineNewValues(&$arr, $keys) {
foreach($keys as $key=>$value){
setValue($key,$value,$arr);
}
}
$myArray=[
"data"=>[
"a"=>[
"content"=>[
"aa"=>[
"price" => 3,
"profit" => 2,
"other" => 1
],
"ab"=>[
"price" => 3,
"profit" => 2,
"other" => 2
]
]
],
"b"=>[
"content"=>[
"ba"=>[
"price" => 3,
"profit" => 2,
"other" => 4
],
"bb"=>[
"price" => 3,
"profit" => 2,
"other" => 5
]
]
],
]
];
defineNewValues($myArray, [
"data.*.content.*.price" => 0,
"data.*.content.*.profit" => 0,
]);
print_r($myArray);
/* OUTPUT
Array
(
[data] => Array
(
[a] => Array
(
[content] => Array
(
[aa] => Array
(
[price] => 0
[profit] => 0
[other] => 1
)
[ab] => Array
(
[price] => 0
[profit] => 0
[other] => 2
)
)
)
[b] => Array
(
[content] => Array
(
[ba] => Array
(
[price] => 0
[profit] => 0
[other] => 4
)
[bb] => Array
(
[price] => 0
[profit] => 0
[other] => 5
)
)
)
)
)
*/
Because the keys you want to replace only occur at one level of the data, the solution doesn't really need to take the entire array structure into account. You can just replace every price and profit key.
array_walk_recursive($example, function(&$value, $key) {
if (in_array($key, ['price', 'profit'])) {
$value = 0;
}
});
Based on your comment on the other answer, my opinion on the "correct and professional way" is that we should try to solve the problem in the simplest way possible, because simple solutions are easy to maintain.
This question already has answers here:
Filter/Remove rows where column value is found more than once in a multidimensional array
(4 answers)
Closed 9 months ago.
I have the following array dynamically generated from an external API:
$purchases = array(
array('product_id' => 7, 'receipt' => R13D13),
array('product_id' => 5, 'receipt' => Y28Z14),
array('product_id' => 7, 'receipt' => R02310),
array('product_id' => 5, 'receipt' => E11403)
);
Desired output:
$purchases_new = array(
array('product_id' => 7, 'receipt' => R13D13),
array('product_id' => 5, 'receipt' => Y28Z14)
);
Due to the nature of the API I have only been able to pull data using array_map:
$purchases_unique = array_unique(
array_map(function($pid){ return $pid['product_id']; }, $purchases)
);
print_r($purchases_unique);
Outputs
array((array[251] => 7) array([252] => 5))
Output completely not what I want :( How to array_map 2 columns product_id' and receipt and remove duplicate rows based on product_id?
I want to achieve the following:
array_map both columns? (product_id and receipt)
Remove product_id duplicates rows based on product_id key?
If you want the first occurrence use #TheFirstBird answer. If you want the last occurrence you can do it simpler buy using array_column and array_values as:
$newArr = array_values(array_column($purchases, null, "product_id"));
Notice the second argument of array_column is null meaning take the entire element.
Live example: 3v4l
References: array-column, array-values
I think this will do what you're looking for:
Just adds the unique product_ids (with receipt) to a new array:
$purchases_new = array_reduce($purchases, function($acc, $p) {
if(!in_array($p['product_id'], array_column($acc, 'product_id'))) {
$acc[] = $p;
}
return $acc;
}, []);
Output:
array (
0 =>
array (
'product_id' => 7,
'receipt' => 'R13D13',
),
1 =>
array (
'product_id' => 5,
'receipt' => 'Y28Z14',
),
)
Try it online!
As per the comment It does not matter if it's the first or last occurrence, you could use a foreach and create a $result array for the non duplicates.
For every iteration, use the product_id as the array key and check if it already has been set.
If it is not, then add it.
$purchases = array(
array('product_id' => 7, 'receipt' => "R13D13"),
array('product_id' => 5, 'receipt' => "Y28Z14"),
array('product_id' => 7, 'receipt' => "R02310"),
array('product_id' => 5, 'receipt' => "E11403")
);
$result = [];
foreach($purchases as $key => $purchase) {
if (!isset($result[$purchase["product_id"]])) {
$result[$purchase["product_id"]] = $purchase;
}
}
print_r($result);
Result
Array
(
[7] => Array
(
[product_id] => 7
[receipt] => R13D13
)
[5] => Array
(
[product_id] => 5
[receipt] => Y28Z14
)
)
Php demo
this is quite beyond me. Appreciate some help.
I have an array in php like so:
[0] => Array
(
[cust_id] => 1006
[no_of_subs] => 2
[dlv_id] => 1000
)
[1] => Array
(
[cust_id] => 1011
[no_of_subs] => 3
[dlv_id] => 1000
)
[2] => Array
(
[cust_id] => 1012
[no_of_subs] => 5
[dlv_id] => 1001
)
[3] => Array
(
[cust_id] => 1013
[no_of_subs] => 6
[dlv_id] => 1001
)
I don't need the cust_id field. I just need to group the dlv_id and the sum of no_of_subs for each matching dlv_id. The result should look like this:
[0] => Array
(
[dlv_id] => 1000
[no_of_subs] => 5
)
[1] => Array
(
[cust_id] => 1011
[no_of_subs] => 11
)
Thank you for any help.
I don't understand the downvotes for this question. Am i doing it all wrong? Downvoting without a reason is not helping.
The simplest, most efficient way to group and sum is to perform a single loop and assign temporary associative keys.
When a row is identified as a new dlv_id row, save the two desired elements, otherwise add the no_of_subs value to the pre-existing value.
Optionally, remove the temporary keys with array_values().
Code (Demo)
$array = [
["cust_id" => 1006, "no_of_subs" => 2, "dlv_id" => 1000],
["cust_id" => 1011, "no_of_subs" => 3, "dlv_id" => 1000],
["cust_id" => 1012, "no_of_subs" => 5, "dlv_id" => 1001],
["cust_id" => 1013, "no_of_subs" => 6, "dlv_id" => 1001]
];
foreach ($array as $row) {
if (!isset($result[$row["dlv_id"]])) {
$result[$row["dlv_id"]] = ["dlv_id" => $row["dlv_id"], "no_of_subs" => $row["no_of_subs"]];
} else {
$result[$row["dlv_id"]]["no_of_subs"] += $row["no_of_subs"];
}
}
var_export(array_values($result));
Output:
array (
0 =>
array (
'dlv_id' => 1000,
'no_of_subs' => 5,
),
1 =>
array (
'dlv_id' => 1001,
'no_of_subs' => 11,
),
)
Using array_column function, we can extract out dlv_id and no_of_subs separately in two different arrays, using cust_id as the key.
Now, simply loop over the array of dlv_id, and if matching key found, add the no_of_subs to it, else set the value (for the first time).
We use isset function to check if the key exists already or not.
Try the following:
// your input array is $input_array
// get all dlv_id maintaining the cust_id as index
$dlv_id = array_column($input_array, 'dlv_id', 'cust_id');
// get all no_of_subs maintaining the cust_id as index
$no_of_subs = array_column($input_array, 'no_of_subs', 'cust_id');
$output = array();
foreach ($dlv_id as $key => $value) {
if (isset($output[$value]['dlv_id'])) {
$output[$value]['dlv_id'] += $no_of_subs[$key];
} else {
$output[$value]['dlv_id'] += $no_of_subs[$key];
}
}
I have multi-dimentional array like below,
$product = array(
"2e471a22b1b994a7cb3f3a40cee9fba2" => array (
"product" => 6004,
"unique_key" => 3a8a5cb029ee3b92cfc90de23e2329ab,
"product_id" => 51,
"line_total"=>99,
"quantity"=>1,
"data"=> array(
"id"=> 51,
"post"=>array(
"ID"=>51,
"post_title"=>"Prodcut four - control",
),
"price"=>99
)
),
"a7d0f813832ec8a2bf24269ff7145d0c" => array (
"product" => 6004,
"unique_key" => c30d1ca26d30aa3dc3c9aa04f0b585ce,
"product_id" => 51,
"line_total"=>99,
"quantity"=>1,
"data"=> array(
"id"=> 51,
"post"=>array(
"ID"=>51,
"post_title"=>"Prodcut four - control",
),
"price"=>99
)
)
);
Need to remove the duplicate values based on 'product_id' array value and increase the quantity values based on number of products.
Note: The above array have 'unique key' too so any single unique key is needed in array result.
Expected Result should be:
$resultproduct = array(
"2e471a22b1b994a7cb3f3a40cee9fba2" => array (
"product" => 6004,
"unique_key" => 3a8a5cb029ee3b92cfc90de23e2329ab,
"product_id" => 51,
"line_total"=>99,
"quantity"=>2,
"data"=> array(
"id"=> 51,
"post"=>array(
"ID"=>51,
"post_title"=>"Prodcut four - control",
),
"price"=>99
)
));
Working code at eval.in
I try and make the code easy to understand so more variables and lines of code than is absolutely required.
Explanation:
1) Need to use the one of original product array index as the output table key e.g. "2e471a22b1b994a7cb3f3a40cee9fba2" for product 51.
2) It needs to be fast relating input productId to the output key. So, I used a lookup table ProductIdList that matches productId to output key.
It is then a two stage lookup to find the entry in the output and add quantities to it.
The code:
// create a product_id => first key table
$productIdList = array();
// output...
$productTotal = array();
foreach ($product as $origIndex => $entry) {
$curProductId = $entry['product_id'];
// check product_id exists in the lookup...
if (isset($productIdList[$curProductId])) { // add to the total...
$productTotalIndex = $productIdList[$curProductId];
$productTotal[$productTotalIndex]['quantity'] += $entry['quantity'];
}
else { // add the entry to the output and the productIdList...
$productIdList[$curProductId] = $origIndex;
$productTotal[$origIndex] = $entry;
}
}
Output: The totals array:
Array
(
[2e471a22b1b994a7cb3f3a40cee9fba2] => Array
(
[product] => 6004
[unique_key] => 3a8a5cb029ee3b92cfc90de23e2329ab
[product_id] => 51
[line_total] => 99
[quantity] => 2
[data] => Array
(
[id] => 51
[post] => Array
(
[ID] => 51
[post_title] => Prodcut four - control
)
[price] => 99
)
)
[test02] => Array
(
[product] => 6664
[unique_key] => c30d1ca26d30aa3dc3c9aa04f0b585ce
[product_id] => 666
[line_total] => 99
[quantity] => 579
[data] => Array
(
[id] => 666
[post] => Array
(
[ID] => 666
[post_title] => Prodcut 666 - control
)
[price] => 99
)
)
)
The productId to original key list:
array (size=2)
51 => string '2e471a22b1b994a7cb3f3a40cee9fba2' (length=32)
666 => string 'test02' (length=6)
You need to loop over each product and use the product_id as the key for a new array. This adds the quantities as it goes, so should work for any quantities other than 1.
$result = [];
foreach ($product as $p)
{
if (isset($result[$p['product_id']]))
{
$result[$p['product_id']]['quantity']+= $p['quantity'];
}
else
{
$result[$p['product_id']] = $p;
}
}
print_r($result);
I have an array
Array(
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[1] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[2] => Array
(
[0] => 33
[user_id] => 33
[1] => 8
[frame_id] => 8
)
[3] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[4] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
As you can see key 0 is the same as 1, 3 and 4. And key 2 is different from them all.
When running the array_unique function on them, the only left is
Array (
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
Any ideas why array_unique isn't working as expected?
It's because array_unique compares items using a string comparison. From the docs:
Note: Two elements are considered
equal if and only if (string) $elem1
=== (string) $elem2. In words: when the string representation is the same.
The first element will be used.
The string representation of an array is simply the word Array, no matter what its contents are.
You can do what you want to do by using the following:
$arr = array(
array('user_id' => 33, 'frame_id' => 3),
array('user_id' => 33, 'frame_id' => 3),
array('user_id' => 33, 'frame_id' => 8)
);
$arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
//result:
array
0 =>
array
'user_id' => int 33
'user' => int 3
2 =>
array
'user_id' => int 33
'user' => int 8
Here's how it works:
Each array item is serialized. This
will be unique based on the array's
contents.
The results of this are run through array_unique,
so only arrays with unique
signatures are left.
array_intersect_key will take
the keys of the unique items from
the map/unique function (since the source array's keys are preserved) and pull
them out of your original source
array.
Here's an improved version of #ryeguy's answer:
<?php
$arr = array(
array('user_id' => 33, 'tmp_id' => 3),
array('user_id' => 33, 'tmp_id' => 4),
array('user_id' => 33, 'tmp_id' => 5)
);
# $arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
$arr = array_intersect_key($arr, array_unique(array_map(function ($el) {
return $el['user_id'];
}, $arr)));
//result:
array
0 =>
array
'user_id' => int 33
'tmp_id' => int 3
First, it doesn't do unneeded serialization. Second, sometimes attributes may be different even so id is the same.
The trick here is that array_unique() preserves the keys:
$ php -r 'var_dump(array_unique([1, 2, 2, 3]));'
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[3]=>
int(3)
}
This let's array_intersect_key() leave the desired elements.
I've run into it with Google Places API. I was combining results of several requests with different type of objects (think tags). But I got duplicates, since an object may be put into several categories (types). And the method with serialize didn't work, since the attrs were different, namely, photo_reference and reference. Probably these are like temporary ids.
array_unique() only supports multi-dimensional arrays in PHP 5.2.9 and higher.
Instead, you can create a hash of the array and check it for unique-ness.
$hashes = array();
foreach($array as $val) {
$hashes[md5(serialize($val))] = $val;
}
array_unique($hashes);
array_unique deosn't work recursive, so it just thinks "this are all Arrays, let's kill all but one... here we go!"
Quick Answer (TL;DR)
Distinct values may be extracted from PHP Array of AssociativeArrays using foreach
This is a simplistic approach
Detailed Answer
Context
PHP 5.3
PHP Array of AssociativeArrays (tabluar composite data variable)
Alternate name for this composite variable is ArrayOfDictionary (AOD)
Problem
Scenario: DeveloperMarsher has a PHP tabular composite variable
DeveloperMarsher wishes to extract distinct values on a specific name-value pair
In the example below, DeveloperMarsher wishes to get rows for each distinct fname name-value pair
Solution
example01 ;; DeveloperMarsher starts with a tabluar data variable that looks like this
$aodtable = json_decode('[
{
"fname": "homer"
,"lname": "simpson"
},
{
"fname": "homer"
,"lname": "jackson"
},
{
"fname": "homer"
,"lname": "johnson"
},
{
"fname": "bart"
,"lname": "johnson"
},
{
"fname": "bart"
,"lname": "jackson"
},
{
"fname": "bart"
,"lname": "simpson"
},
{
"fname": "fred"
,"lname": "flintstone"
}
]',true);
example01 ;; DeveloperMarsher can extract distinct values with a foreach loop that tracks seen values
$sgfield = 'fname';
$bgnocase = true;
//
$targfield = $sgfield;
$ddseen = Array();
$vout = Array();
foreach ($aodtable as $datarow) {
if( (boolean) $bgnocase == true ){ #$datarow[$targfield] = #strtolower($datarow[$targfield]); }
if( (string) #$ddseen[ $datarow[$targfield] ] == '' ){
$rowout = array_intersect_key($datarow, array_flip(array_keys($datarow)));
$ddseen[ $datarow[$targfield] ] = $datarow[$targfield];
$vout[] = Array( $rowout );
}
}
//;;
print var_export( $vout, true );
Output result
array (
0 =>
array (
0 =>
array (
'fname' => 'homer',
'lname' => 'simpson',
),
),
1 =>
array (
0 =>
array (
'fname' => 'bart',
'lname' => 'johnson',
),
),
2 =>
array (
0 =>
array (
'fname' => 'fred',
'lname' => 'flintstone',
),
),
)
Pitfalls
This solution does not aggregate on fields that are not part of the DISTINCT operation
Arbitrary name-value pairs are returned from arbitrarily chosen distinct rows
Arbitrary sort order of output
Arbitrary handling of letter-case (is capital A distinct from lower-case a ?)
See also
php array_intersect_key
php array_flip
function array_unique_recursive($array)
{
$array = array_unique($array, SORT_REGULAR);
foreach ($array as $key => $elem) {
if (is_array($elem)) {
$array[$key] = array_unique_recursive($elem);
}
}
return $array;
}
Doesn't that do the trick ?
`
$arr = array(
array('user_id' => 33, 'tmp_id' => 3),
array('user_id' => 33, 'tmp_id' => 4),
array('user_id' => 33, 'tmp_id' => 3),
array('user_id' => 33, 'tmp_id' => 4),
);
$arr1 = array_unique($arr,SORT_REGULAR);
echo "<pre>";
print_r($arr1);
echo "</pre>";
Array(
[0] => Array(
[user_id] => 33
[tmp_id] => 3
)
[1] => Array(
[user_id] => 33
[tmp_id] => 4
)
)
`