How to merge two arrays with duplicate keys - php

I have two arrays $rate_row and $totalrowcost I am trying to update a row in the second array $totalrowcost based on the key in the first array $rate_row both arrays are always the same length.
I combine both arrays using the array_combine function
my code below works if there are no duplicate keys in the array but if i combine them when there are duplicate keys
I don't get the desired result.
Example:
If the key in $rate_row is 0 I need to set the value in $totalrowcost to 0 but when combining the array, one of the rows gets dropped and only one row with a key of 0 is preserved.
I've since learned since trying to figure this out that PHP will not allow an array to have a duplicate key, but i was wondering if there is some type of work around or hack that can help any ideas would be great thanks.
enter code here
<?php
// Finds the lowest duty rate
$lowest = 0;
$row_combine = array_combine($rate_row, $totalrowcost);
foreach($row_combine as $a => $combine_row):
if ($a = 0){
$lowest = $a;
echo "";
}
endforeach;
// Finds the row value associated with the lowest duty rate
foreach($row_combine as $a => $combine_row):
if ($a === $lowest){
$lowest1 = $combine_row;
}
endforeach;
for($i = 0; $i < count($totalrowcost); $i++) {
enter code here
if ($totalrowcost[$i] == $lowest1){
$totalrowcost[$i] = 0;
}
}?>
enter code here
$rate_row
Array
(
[0] => 35
[1] => 0
[2] => 40
[3] => 0
[4] => 45
)
$totalrowcost
Array (
[0] => 100
[1] => 49.99
[2] => 102
[3] => 98
[4] => 125
)
$row_combine Output
Array (
[35] => 100
[0] => 98
[40] => 102
[45] => 125
)
Desired $row_combine Output
Array (
[35] => 100
[0] => 49.99
[40] => 102
[0] => 98
[45] => 125
)
Actual Output updated
$totalrowcost
Array (
[0] => 100
[1] => 49.99
[2] => 102
[3] => 0
[4] => 125
)
Desired Output updated
$totalrowcost
Array (
[0] => 100
[1] => 0
[2] => 102
[3] => 0
[4] => 125
)

documentation for class to read up on the syntax and more information about them.
I'm a little unclear as to what problem you are trying to solve, perhaps an edit on what the use case is might help suggest other options.
EDIT:
<?php
// you can use whatever input $rate_row is from user input or such along with the $totalrowcost
$rate_row = [35, 0, 40, 0, 45];
$totalrowcost = [100, 49.99, 102, 98, 125];
class Table {
public $row_items;
public $row_rates;
public $row_rate_applied;
private $lowestRate;
// used to init class values
function __construct($items, $rates) {
// set variables to class
// might want to run validation here to make sure the count is = for $items and $rates
$this->row_items = $items;
$this->row_rates = $rates;
$this->lowestRate = min($rates); // add validation to make sure rates is array http://php.net/manual/en/function.min.php
// main guts that are used to solve your problem is inside this loop
for($i = 0; $i < count($items); $i++) {
// here we test if rates index == lowest. if it is set the item value to lowest
if ($rates[$i] == $this->lowestRate) {
$this->row_rate_applied[$i] = $this->lowestRate;
} else {
$this->row_rate_applied[$i] = $items[$i];
}
}
}
}
$table = new Table($totalrowcost, $rate_row);
echo var_dump($table->row_rate_applied);
The above code builds up and applies the rates against the items. I'm not 100% what the expected result is actually supposed to be because the code originally posted doesn't make a ton of sense for the expected output
essentially the idea is to build your Row

If the keys have no significant value (i.e. you just want to later loop over the final array) you can make sure the keys are unique before you merge them by appending a random name at the end of them.
Here is a function that merges two arrays while keeping the duplicate keys.
function array_uniqify_keys($array,$append='',$glue='--'){
if($append === ''){
$append = uniqid() . mt_rand(1000,9999);
}
foreach($array as $key => $value){
unset($array[$key]);
$array[$key.$glue.$append] = $value;
}
return $array;
}
function array_merge_duplicate_safe($array1,$array2,$a1_name='',$a2_name=''){
$array1 = array_uniqify_keys($array1,$a1_name);
$array2 = array_uniqify_keys($array2,$a2_name);
return array_merge($array1,$array2);
}
$array1 = [
1 => 'foo',
2 => 'boo'
];
$array2 = [
1 => 'good',
2 => 'bad',
3 => 'ugly'
];
print_r(array_merge_duplicate_safe($array1,$array2));
The result for the above code is:
Array
(
[1--59d393950489c8380] => foo
[2--59d393950489c8380] => boo
[1--59d39395049197021] => good
[2--59d39395049197021] => bad
[3--59d39395049197021] => ugly
)
You can also get the old key by explode('--',$key)[0].

Related

How can I add a value from one array to a new empty associative array in PHP?

I want to count how many times a number exists in my array, but I want to do it like this.
I have an empty array like this:
$aNumberArray = array();
And I have an array like this:
$aArray = (4,4,5,7,4,8,7,9,4,3);
This is my code so far:
foreach ($aArray as $value) {
if (in_array($value, $aNumberArray)) {
// increase value in $aNumerArray.
}else{
// add $value from $aArray to $aNumberArray as key and as value add 1.
}
}
I want to know how I can add the value from $aArray to $aNumberArray as a key and I want to add number 1 as value. When It excist it most increase the value from $aArray.
Here you go:
<?php
$aNumberArray = array();
$aArray = array(4,4,5,7,4,8,7,9,4,3);
foreach ($aArray as $value) {
if (!isset($aNumberArray[$value])) {
$aNumberArray[$value] = 0;
}
$aNumberArray[$value] += 1;
}
print_r($aNumberArray);
Will give you:
Array
(
[4] => 4
[5] => 1
[7] => 2
[8] => 1
[9] => 1
[3] => 1
)
Check output of it
$aArray = [4,4,5,7,4,8,7,9,4,3]; // correct this array format
print_r(array_count_values($aArray));
Output
Array
(
[4] => 4
[5] => 1
[7] => 2
[8] => 1
[9] => 1
[3] => 1
)
Demo
array_count_values — Counts all the values of an array

Search array input key in array

How do I find the keys array of disciplines that have appropriate values?
For Example:
$arr1 = [2, 4, 12];
$result = [...] // Var_dump in link
in_array($arr1, $result);
Regardless of their order, I need to see if there is a set of keys or a no.
But in_array() does not work.
Thanks!
Dump array
Update (01.03.2017)
This is my version of the solution to this problem
$findResult = array_filter($result, function($val)use($get){
$requiredDisciplines = [1, $get['disciplines']['second'], $get['disciplines']['third'], $get['disciplines']['four']]; // запрос
$activePriorities = [];
foreach ($val['disciplines'] as $discipline) {
if (in_array($discipline['id'], $requiredDisciplines)) {
$activePriorities[] = $discipline['priority'];
}
}
for ($i = 0; $i<3; $i++){
if(!in_array($i, $activePriorities))
return false;
}
/*if(in_array(0, $activePriorities) && in_array(1, $activePriorities) && in_array(2, $activePriorities) != true)
return false;*/
// print_r($activePriorities);
return true;
});
I've got a versatile one-liner that will give you all of the arrays containing matches. (so you can derive the keys or the count from that). (demo)
This function is only set to compare the values between the needle and the haystack, but can be set to search keys-values pairs by replacing array_intersect with array_intersect_assoc and adding ,ARRAY_FILTER_USE_BOTH to the end of the filter function (reference: 2nd snippet # https://stackoverflow.com/a/42477435/2943403)
<?php
// haystack array
$result[]=array(1,2,3,4,5,6,7,8,9,10,11,12);
$result[]=array(1,3,5,7,9,11);
$result[]=array(2,4,6,8,10,12);
// needle array
$arr1=array(2,4,12);
//one-liner:
$qualifying_array=array_filter($result,function($val)use($arr1){if(count(array_intersect($val,$arr1))==count($arr1)){return $val;}});
/*
// multi-liner of same function:
$qualifying_array=array_filter(
$result,
function($val)use($arr1){ // pass in array to search
if(count(array_intersect($val,$arr1))==count($arr1)){ // total pairs found = total pairs sought
return $val;
}
}
);*/
echo 'Total sub-arrays which contain the search array($arr1): ',sizeof($qualifying_array),"<br>";
echo 'Keys of sub-arrays which contain the search array($arr1): ',implode(',',array_keys($qualifying_array)),"<br>";
echo 'Is search array($arr1) in the $result array?: ',(sizeof($qualifying_array)?"True":"False"),"<br>";
echo "<pre>";
print_r($qualifying_array);
echo "</pre>";
The output:
Total sub-arrays which contain the search array($arr1): 2
Keys of sub-arrays which contain the search array($arr1): 0,2
Is search array($arr1) in the $result array?: True
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
[8] => 9
[9] => 10
[10] => 11
[11] => 12
)
[2] => Array
(
[0] => 2
[1] => 4
[2] => 6
[3] => 8
[4] => 10
[5] => 12
)
)

Combine 2 arrays in PHP

I have 2 arrays that I need to combine or merge together. I am at a bit of a loss as to how to achieve this.
So the first array looks like this:
$arr1 =
Array (
[0] => Array
(
[id] => 7
[round] => 1
)
[1] => Array
(
[id] => 11
[round] => 2
)
....
And the second array looks like this:
$arr2 =
Array (
[round_1] => 21
[round_2] => 32
....
And I need the result to end up like this:
$result =
Array (
[0] => Array
(
[id] => 7
[round] => 1
[disp] => 21
)
[1] => Array
(
[id] => 11
[round] => 2
[disp] => 32
)
...... etc etc
Any ideas on where to get started for this??
Thanks
$i = 1; // Counter
$result = $arr1; // Copy $arr1 to preserve it. (if necessary)
foreach ($result as $x){
$x['disp'] = $arr2['round_' . $i];
$i ++;
}
This will iterate through Array1 setting a value for 'disp' in each sub array. This value will be pulled from Array2 and the round number would be incremented by a basic counter.
You could equally use a standard for loop for this too.
$result = $arr1; // Copy $arr1 to preserve it. (if necessary)
for($i = 0; $i < count($result); $i++){
$result[$i]['disp'] = $arr2['round_' . ($i + 1)];
}
Just make sure you do "$i + 1" when calling the value from Array2 because that doesn't seem to be 0 indexed.

How to check if an array index contains a value

I have an array with some values in different spots. I want to check if there is a value in the index then put it in a new array starting at 0 then put in index 1 then next value at index 2 and so on. I need to shorten it and move them all to the left really.
Array ( [0] => 53 [1] => [2] => 55 [3] => 76 [4] => [5] => [6] => [7] => )
The new array would be:
newArray ( [0] => 53 [1] =>55 [2] => 76)
Maybe something like this:
for ($i=0; $i < sizeof($questionWorth); $i++)
{
if($questionWorth[$i] has a value)
{
put it in new array starting at index zero
then increment the index of new array
}
}
To only get values that is not NULL or empty you could use array_filter() and array_values() like this:
$array = array(76, NULL, NULL, 56);
// remove empty values from array, notice that since no callback
// is supplied values that evaluates to false will be removed
$array = array_filter($array);
// since array_filter will preserve the array keys
// you can use array_values() to reindex the array numerically
$array = array_values($array);
// prints Array ( [0] => 76 [1] => 56 )
print_r($array);
You can use
array_filter($yourArray)
It will remove all empty values for you
Try array_filter which makes exactly this
var_dump(array_filter(array(0 => 55, 1 => 60, 2 => null)))
If you want to check if an index has a value, do this :
$variable = array ([0] => 53, [1] => , [2] => 55, [3] => 76, [4] => , [5] => , [6] => , [7] => )
foreach ($variable as $key => $value) {
var_dump($key.' => '.$value);
}
It's as simple as this: if ( $array [$i] ), and then put the value in another array with another counter that starts from 0.
$array = array(76, NULL, NULL, 56);
$count = 0;
for ($i=0; $i < sizeof($array); $i++)
{
if($array[$i])
{
$arr[$count] = $array[$i];
$count++;
}
};
print_r($array);
print_r($arr);

Minimum Match Logic

I have a very large data set that I'm trying to find the smallest set that will satisfy all the data sets. The final set must have one value in it that is in all of the data sets
A small sample of the data looks like
[0] => Array
(
[0] => 21
[1] => 21
[2] => 21
)
[1] => Array
(
[0] => 29
)
[2] => Array
(
[0] => 27
)
[3] => Array
(
[0] => 21
[1] => 21
[2] => 21
[3] => 39
[4] => 39
[5] => 43
)
[4] => Array
(
[0] => 29
[1] => 33
[2] => 33
[3] => 43
)
In this case I need logic to return 21, 27 and 29
The values returned needs to be be the minium number of values that match all arrays. Since I'm a PHP programmer, I writing this function in PHP.
You could follow this algorithm:
Updated after testing
$data=array(
array(21,29,27,57,22),
array(22,21,23,24,25,26),
array(31)
);
$map = array(); // keep a map of values and how many times they occur in other sets
foreach ($data as $setid => $set) {
foreach (array_unique($set) as $v) {
$map[$v][$setid] = true;
}
}
function reverseCount(array $a, array $b)
{
return count($b) - count($a);
}
// sort reversed on intersection count
uasort($map, 'reverseCount');
// after sorting the first number will be the one that occurs the most
// keep track of which sets have been hit
$setmap = array(); $n = count($data);
foreach ($map as $v => $sets) {
$hits = 0;
foreach ($sets as $setid => $dummy) {
if (!isset($setmap[$setid])) {
--$n;
++$hits;
$setmap[$setid] = true;
} else {
continue;
}
}
if ($hits) {
echo "value $v\n";
if (!$n) {
// all sets are hit
break;
}
}
}
Tested this time. It's not proven to always get the right result, because this is considered a greedy approximation algorithm.
But I hope it gives an idea of what you could do. Let me know if anything confuses you or if I'm dead wrong about it :)

Categories