I have following $data array
Array
(
[0] => Array
(
[match_day] => MD27
[price] => 95.33
)
[1] => Array
(
[match_day] => MD28
[price] => 97.82
)
[2] => Array
(
[match_day] => MD29
[price] =>
)
[3] => Array
(
[match_day] => MD30
[price] =>
)
[4] => Array
(
[match_day] => MD31
[price] =>
)
)
Now, my requirements is - replace empty entry of price attribute with previous price attribute.
No need to go for for loop You can try following code:
$result = [];
array_walk($data, function($v,$k) use (&$result){
$result[$k] = $v;
if(!isset($result[$k]['price']) || $result[$k]['price'] == null){
$result[$k]['price'] = $result[$k - 1]['price'];
}
});
print_r($result);
Working Demo is Here
Perform a foreach loop an your array, store previous price value and if the current item has empty price, use previous to replace it. Example:
$previous = 0;
foreach($data AS $key => $row) {
if (empty($row['price']))
$data[$key]['price'] = $previous;
else
$previous = $row['price'];
}
Related
I have this code:
$order = wc_get_order( 988613 );
$product_array = array();
$daty = array();
$counter = 1;
foreach ($order->get_items() as $item_key => $item ){
$daty_dostaw = $item->get_meta('Daty dostaw');
$product_id = $item->get_product_id();
$daty_dostaw_explode = explode(',',$daty_dostaw);
$daty[$counter]['product_id'] = $product_id;
foreach($daty_dostaw_explode as $key => $data){
$daty[$counter]['data'][] = $data;
}
$counter++;
}
When I print it it shows me this
Array
(
[1] => Array
(
[product_id] => 988012
[data] => Array
(
[0] => 13-08-2022
[1] => 25-08-2022
[2] => 30-08-2022
)
)
[2] => Array
(
[product_id] => 988087
[data] => Array
(
[0] => 25-08-2022
[1] => 31-08-2022
[2] => 30-09-2022
)
)
)
I want to combine an array that have the same dates to display like this:
Array
( [1] => Array
(
[product_id] => array(988012, 988087)
[data] => Array
(
[0] => 25-08-2022
)
)
[2] => Array
(
[product_id] => 988012
[data] => Array
(
[0] => 13-08-2022
[1] => 30-08-2022
)
)
[3] => Array
(
[product_id] => 988087
[data] => Array
(
[0] => 31-08-2022
[1] => 30-09-2022
)
)
)
I want to merge the array those with the same dates. I don't know how to explain it exactly, above I showed what I would like to achieve. I have already written thousands of lines of code using foreach and have not been able to achieve this :(
Basically you want to convert product_id into an array if there are multiple products with the same date. I would search for such matches, create the merges, remove the elements from the individual occurrence or even the individual occurrence if it gets emptied. An example would be this:
$cachedDates = []; //Here we will store the dates we have gone through so far
foreach ($product_array as $key => $product) {
foreach ($product_array[$key]["data"] => $date) {
if (!in_array($date, $cachedDates)) {
//Creating a cache entry for this date
$cachedDates[$date] = ["keys" => [], "values" => []];
}
//Adding the key and product to the date's cache
$cachedDates[$date]["keys"][]= $key;
$cachedDates[$date]["values"][]= $product["product_id"];
}
}
//Adding the new items to $product_array and cleaning up items that become redundant
foreach ($cachedDates as $date => $entry) {
//We only merge items that have a not-unique date
if (count($entry["values"]) > 0) {
//adding a new item with the correct values and the date
$product_array[]= [
"product_id" => $entry["values"],
"data" => $date
];
//Cleanup
for ($index = 0; $index < count($entry["keys"]); $index++) {
//We remove the date from the data entry after finding its index
$removeIndex = array_search($date, $product_array[$entry["keys"][$index]]["data"]);
unset($product_array[$entry["keys"][$index]]["data"][$removeIndex]);
//If the data array is empty, then the whole product was already merged into some other item(s)
if (!count($product_array[$entry["keys"][$index]]["data"])) {
unset($product_array[$entry["keys"][$index]]);
}
}
}
}
The code above was untested, if you find issues with it and errors, then provide the appropriate PHP input instead of its print, even a json_encode result is good-enough
Im creating an array of products, each with an ID and score:
$savedProducts = array( 'product' => array("product_id" => $product_id,"product_score" => $score));
I want to be able to update the score by using the product_id as identifier.
I've tried:
foreach($savedProducts as $key => $val)
{
if ($val == $property_id )
{
$savedProducts[$key] = $score;
break;
}
}
Which keeps adding a new array item, rather than updating the original.
I think the issue is that my initial array setup then doesn't match the edited one.
Initial array:
Array
(
[product] => Array
(
[product_id] => 125026
[product_score] => 5
)
)
After trying to update score:
Array
(
[0] => Array
(
[product] => Array
(
[product_id] => 125026
[product_score] => 4
)
)
[1] => Array
(
[0] => Array
(
[product] => Array
(
[product_id] => 125026
[product_score] => 4
)
)
)
)
So it keeps addding elements, rather than updating the existing.
with PHP 5.5 use:
$savedProducts = array_column($savedProducts, NULL, 'product_id');
then you can access your product with:
$savedProducts[$product_id]
Please try this
foreach($savedProducts as $key => $val)
{
if($val['product_id'] == $property_id)
{
$savedProperties[$key]['product_score'] = $score;
break;
}
}
I have a fairly simple multidimensional array that I need to dedupe. I also need to remove any key that has a value, so in the below code I would need to keep the second target/value of city/Paris (Array 3) and also remove the 6th Array.
Array
(
[0] => Array
(
[target] => city
[value] => London
)
[1] => Array
(
[target] => colour
[value] => Red
)
[3] => Array
(
[target] => city
[value] => Paris
)
[4] => Array
(
[target] => type
[value] => House
)
[6] => Array
(
[target] => name
[value] =>
)
[7] => Array
(
[target] => email
[value] => mail#gmail.com
)
[9] => Array
(
[target] => custom2
[value] => path/to/something
)
)
I can do this by:
Flattening the array
Assigning the target/value as new key/values (this automatically overwrites the later value if there are dupes)
Remove any keys that have a value of
Rebuild the array
This feels wrong and I'm sure there is a better solution using array_walk_recursive() as this would probably preserve the original keys and make for a more elegant solution.
This is my current code:
function _clean_and_dedupe_targeting($array) {
// First flatten the array.
$flattenned = array();
foreach ($array as $item) {
foreach ($item as $value) {
$flattenned[] = $value;
}
}
// Take alternate items as key/value pairs.
// THIS WILL OVERWRITE ANY DUPLICATES LEAVING THE ONE SET IN CONTEXT IN PLACE.
$keyval = array();
array_unshift($flatenned, false);
while (false !== $key = next($flattenned)) {
$keyval[$key] = next($flattenned);
}
// Remove any items with <REMOVE>
$remove_string = '<REMOVE>';
$remove_keys = array_keys($keyval, $remove_string);
// Remove any keys that were found.
foreach ($remove_keys as $key) {
unset($keyval[$key]);
}
// Rebuild the array as a multidimensional array to send to the js.
$targeting = array();
$i = 0;
foreach ($keyval as $target => $value) {
$targeting[$i] = array('target' => $target, 'value' => $value);
$i++;
}
return $targeting;
}
Your algorithm is exactly what you would do:
// flatten and remove empty values
$params = array();
foreach ($values as $value) {
if (!empty($value['value'])) {
$params[$value['target']] = $value['value'];
}
}
// rebuild array
$values = array();
foreach ($params as $target => $value) {
$values[] = array(
'target' => $target,
'value' => $value,
);
}
I'm having a strange problem while building arrays. I start off with an array that looks like this:
Array (
[0] => Array (
[tag_id] => 19
[tag_translation_id] => 12
[fk_language_id] => 1
[fk_tag_id] => 19
[tag_name] => test
)
[1] => Array (
[tag_id] => 20
[tag_translation_id] => 14
[fk_language_id] => 1
[fk_tag_id] => 20
[tag_name] => testa
)
[2] => Array (
[tag_id] => 20
[tag_translation_id] => 15
[fk_language_id] => 3
[fk_tag_id] => 20
[tag_name] => fdfda
)
)
What I want to do is merge each result with the same tag_id into a single array. This works:
$tags = array();
foreach($results->as_array() as $key=>$result)
{
if(!in_array($result['tag_id'], $tags))
{
$tags[$result['tag_id']] = array();
}
}
foreach($results->as_array() as $result)
{
array_push($tags[$result['tag_id']], array($result['fk_language_id'] , $result['tag_name']));
}
Here is the intended result:
Array (
[19] => Array (
[0] => Array (
[0] => 1
[1] => test
)
)
[20] => Array (
[0] => Array (
[0] => 1
[1] => testa
)
[1] => Array (
[0] => 3
[1] => fdfda
)
)
)
However, I've got two loops here, and I know this isn't ideal. Why do THESE not work??
$tags = array();
foreach($results->as_array() as $key=>$result)
{
$tags[$result['tag_id']] .= array($result['fk_language_id'] , $result['tag_name']);
}
With this example I get two empty arrays...
Array ( [19] => Array [20] => ArrayArray )
Or even...
$tags = array();
foreach($results->as_array() as $key=>$result)
{
if(!in_array($result['tag_id'], $tags))
{
$tags[$result['tag_id']] = array();
}
array_push($tags[$result['tag_id']], array($result['fk_language_id'] , $result['tag_name']));
}
Which for some reason overwrites the first value of the second array with the second value of the second array.
Array (
[19] => Array (
[0] => Array (
[0] => 1
[1] => test
)
)
[20] => Array (
[0] => Array (
[0] => 3
[1] => fdfda
)
)
)
What am I doing wrong in the second 2 examples?
To answer your question, your second method fails because you're using the incorrect .= operator. Your third method fails because your !in_array check is always false (it checks whether the value is in the array, not whether the key is set) and overwrites the array each iteration. You only really need this (as mentioned by others, in pseudo-code):
$result = array();
foreach ($array as $values) {
$result[$values['key']][] = array($values['foo'], $values['bar']);
}
The .= operator is string concatenation. Arrays are merged with +=.
If I understand the issue correctly, the code should go like this:
$tags = array();
foreach ($results as $result)
$tags[$result['tag_id']][] = array($result['fk_language_id'], $result['tag_name']);
$tags = array();
foreach($results->as_array() as $key=>$result)
{
$tags[$result['tag_id']] .= array($result['fk_language_id'] , $result['tag_name']);
}
you cannot add a value to an array with the .= (dot equal) operator.
why are you doing $results->as_array() ????
do simply:
foreach($results as $key=>$result) {
Instead of using .= try using []
$tags = array();
foreach ($results as $result)
{
if(!isset($tags[$result['tag_id']]))
$tags[$result['tag_id']] = array();
$tags[$result['tag_id']][] = array($result['fk_language_id'], result['tag_name']);
}
.= is to concatinate a string
+= is to concatinate a number
[] is to concatinate to an array
Hope this helps?
Edit: Noticed that it "might" fail if the tag_id doesn't already exist in the array, so it might be worth just checking first and setting it to an array just in case.
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);
}