Complex & Confusing PHP Array Calculations - php

I have set of data that I need help with. I need to make a difficult calculation and array sort through several multidimensional arrays and the logic and syntax is giving me a headache.
Basically what I need it:
an array of keywords
I need to query a database and store some results for each keyword. (ID and Count of keyword matches)
I need to then flip the array around so instead of keywords being the parent element, it's IDs with the count of matches for each keyword within
I need to perform a calculation to get a single number from these number of matches
I need to sort the array so I can see which ID yielded the highest match value in the database, so I can query and output the relevant data.
I know how I am going to do the calculation for the relevancy now, it's just I've only briefly worked with single dimension arrays and I don't know how to syntactically represent what I need with this example. Could anyone give me a hand?
Here is a sample of what I want - not sure if this is syntactically the best way to show you, but hopefully you'll get the picture:
Array
(
[Keywords] => Array
(
["wax"] => Array
(
[ID] => 1
[Match] => 8
[ID] => 2
[Match] => 10
)
["hard"] => Array
(
[ID] => 1
[Match] => 2
[ID] => 2
[Match] => 37
)
)
Then this array would need to be translated to:
Array
(
[ID] => Array
(
["1"] => Array
(
[Keyword] => "wax"
[Match] => 8
[Keyword] => "hard"
[Match] => 10
)
["2"] => Array
(
[Keyword] => "wax"
[Match] => 2
[Keyword] => "hard"
[Match] => 37
)
)

This code:
$arr = array
(
"wax" => array
(
array(
'ID' => 11,
'Match' => 8
),
array(
'ID' => 21,
'Match' => 10
)
),
"hard" => array
(
array(
'ID' => 11,
'Match' => 2
),
array(
'ID' => 21,
'Match' => 37
)
)
);
$byid = array();
foreach($arr as $kw => $res) {
foreach($res as $r) {
$byid[$r['ID']][] = array('Keyword' => $kw, 'Match' => $r['Match']);
}
}
var_export($byid);
gives:
array (
11 =>
array (
0 =>
array (
'Keyword' => 'wax',
'Match' => 8,
),
1 =>
array (
'Keyword' => 'hard',
'Match' => 2,
),
),
21 =>
array (
0 =>
array (
'Keyword' => 'wax',
'Match' => 10,
),
1 =>
array (
'Keyword' => 'hard',
'Match' => 37,
),
),
)
I hope it helps.

You can query the db and create both the arrays by,
$query = "select id, keyword, count(*) as keyword_count from [your table] group by keyword";
$result = mysql_query($query);
while($row = mysql_fetch_array($result)){
$keyword = $row['keyword'];
$id = $row['id'];
$count = $row['keyword_count'];
$first_array["keywords"]["$keyword"] = array('id' => $id, 'match' => $count);
$second_array["id"]["$id"] = array('keyword' => $keyword, 'match' => $count);
}
print_r($first_array);
print_r($second_array);

Related

How can match two array in php

I have two array:
One Array
$workingDays = ['2019-11-01','2019-11-02','2019-11-03','2019-11-04'];
Other Array
$doneWork = array(
array(
'id' => 1,
'date' => '2019-11-01',
'work' => 'done'
),
array(
'id' => 1,
'date' => '2019-11-02',
'work' => 'done'
),
array(
'id' => 1,
'date' => '2019-11-04',
'work' => 'done'
)
);
My Question: How can check which date not exist in $doneWork array
You'd start by extracting the dates from $doneWork using array_map.
$doneWork = [
[
'id' => 1,
'date' => '2019-11-01',
'work' => 'done',
],
[
'id' => 1,
'date' => '2019-11-02',
'work' => 'done',
],
[
'id' => 1,
'date' => '2019-11-04',
'work' => 'done',
],
];
$doneWorkDays = array_map(function ($element) {
return $element['date'];
}, $doneWork);
print_r($doneWorkDays);
Will print:
Array ( [0] => 2019-11-01 [1] => 2019-11-02 [2] => 2019-11-04 )
Then check which elements in $workingDays are not in such array, using array_diff
$diff = array_diff($workingDays, $doneWorkDays);
print_r($diff);
Will print:
Array ( [2] => 2019-11-03 )
Pay attention, the result gives you not only the elements but also their index in the original array. If you don't care about these, use instead:
print_r(array_values($diff));
Why would anyone need such index? Well, perhaps you could need to report not only how many days were missed but also check if two missing elements are adjacent.
(the indexes are relevant only for the array you're comparing against. It doesn't matter in what position they appear in $doneWork )
Edit:
You say you need the results to be in "doneWork" format, which is an associative array with id (always zero), date and work (always 'absent').
Let's say your workin days are now
$workingDays = [
'2019-11-01',
'2019-11-02',
'2019-11-03',
'2019-11-04',
'2019-11-05'
];
So there are two missing days. Again, array map to the rescue:
// from previous answer
$diff = (array_diff($workingDays, $doneWorkDays));
// map each missing date to a doneWork array
$diff_assoc = array_values(
array_map(function($date) {
return [
'id' => 0,
'date' => $date,
'work' => 'absent'
];
},$diff)
);
That will return
Array
(
[0] => Array
(
[id] => 0
[date] => 2019-11-03
[work] => absent
)
[1] => Array
(
[id] => 0
[date] => 2019-11-05
[work] => absent
)
)
Again, note I'm wrapping the result in array_values because you need a plain array as result instead of:
Array
(
[2] => Array
(
[id] => 0
[date] => 2019-11-03
[work] => absent
)
[4] => Array
(
[id] => 0
[date] => 2019-11-05
[work] => absent
)
)
$nonExistingDates = [];
$doneWorkDays = [];
foreach($doneWork as $work) {
$doneWorkDays[] = $work['date'];
}
$nonExistingDates = array_diff($workingDays, $doneWorkDays);
// optional, removes duplicate dates
$nonExistingDates = array_unique($nonExistingDates);

How to assign indexed array values to multidimensional array?

I'd like to replace the values of a multidimensional array with the values of a simple numerically indexed array. The number of values in each array is equal, but they do not have the same keys/indexes due to different array structure.
I had a working solution using array_combine, iteration, and a hashtable but cannot recreate my work. I've tried array_merge, array_combine, and looping through the arrays.
$venue_ids = array(
0 => array(
0 => 2476 ),
1 => array(
0 => 2482,
1 => 2480,
2 => 2463 ),
2 => array(
0 => 2484,
1 => 2476,
2 => 2486,
3 => 2463 ));
$names = array(
0 => 'clubhouse',
1 => 'campground',
2 => 'lake',
3 => 'range',
4 => 'trfields',
5 => 'clubhouse',
6 => 'trfields',
7 => 'range' );
I'd like the result to keep the structure of the first array, and simply substitute its values with those from the second. It should look like this:
$venues = array(
0 => array(
0 => 'clubhouse' ),
1 => array(
0 => 'campground',
1 => 'lake',
2 => 'range' ),
2 => array(
0 => 'trfields',
1 => 'clubhouse',
2 => 'trfields',
3 => 'range' ));
The configuration of $venue_ids will change, including the number of indexes and number of keys/values therein, but there will always be a matching 1-to-1 number of $names. I'd be happy just replacing values or constructing a whole new array matching the structure of $venues_id and working with that.
You should probably ask a new question about the queries to see if you can get the correct result to begin with, but in the meantime you can use array_walk_recursive to substitute the values:
array_walk_recursive($venue_ids, function (&$v) use (&$names) { $v = array_shift($names); });
print_r($venue_ids);
Output:
Array
(
[0] => Array
(
[0] => clubhouse
)
[1] => Array
(
[0] => campground
[1] => lake
[2] => range
)
[2] => Array
(
[0] => trfields
[1] => clubhouse
[2] => trfields
[3] => range
)
)
Demo on 3v4l.org

PHP Match by common key of two multidimentional array and merge the two array with both array key [duplicate]

This question already has answers here:
PHP merge two arrays on the same key AND value
(5 answers)
Closed 4 years ago.
Good evening, I have a little bit problem. I have two array. like
$firstArr = Array(
[0] => Array(
[customer_id] => 11,
[home_delivery] => no,
),
[1] => Array(
[customer_id] => 12,
[home_delivery] => no,
),
[2] => Array(
[customer_id] => 13,
[home_delivery] => no,
),
);
$secondArr = Array(
[0] => Array(
[customer_id] => 11,
[test] => no,
[is_active] => yes,
),
[1] => Array(
[customer_id] => 22,
[test] => no,
[is_active] => yes,
),
);
Now i want to get the result like first array's customer_id match with the second array customer_id. Id two array's customer id is same the the value of second array add with first array otherwise the value will be null. Hope guys you got my point what i want. The output which i want is like the below.
$getResult = Array(
[0] => Array(
[customer_id] => 11,
[home_delivery] => no,
[test] => no,
[is_active] => yes,
),
[1] => Array(
[customer_id] => 12,
[home_delivery] => no,
[test] => '',
[is_active] => '',
),
[2] => Array(
[customer_id] => 13,
[home_delivery] => no,
[test] => '',
[is_active] => '',
),
);
I have tried by this code, but it doesnt work. Please help me.
$mergedArray = array();
foreach ($firstArr as $index1 => $value1) {
foreach ($secondArr as $index2 => $value2) {
if ($array1[$index1]['customer_id'] == $array2[$index2]['customer_id']) {
$mergedArray[] = array_merge($firstArr[$index1], $secondArr[$index2]);
}
}
}
echo "<pre>"; print_r($mergedArray); echo "</pre>";
You can do this :
<?php
$results = [];
// Get all unique keys from both arrays
$keys = array_unique(array_merge(array_keys($firstArr[0]), array_keys($secondArr[0])));
// Make array of common customer_ids
foreach (array_merge($firstArr, $secondArr) as $record) {
$results[$record['customer_id']] = isset($results[$record['customer_id']]) ? array_merge($results[$record['customer_id']], $record) : $record;
}
// Fill keys which are not present with blank strings
foreach ($keys as $key) {
foreach ($results as $index => $result) {
if(!array_key_exists($key, $result)){
$results[$index][$key] = '';
}
}
}
print_r($results);
This is how I would do it:
$firstArr = array (
0 =>
array (
'customer_id' => 11,
'home_delivery' => 'no'
),
1 =>
array (
'customer_id' => 12,
'home_delivery' => 'no'
),
2 =>
array (
'customer_id' => 13,
'home_delivery' => 'no'
)
);
$secondArr = array (
0 =>
array (
'customer_id' => 11,
'test' => 'no',
'is_active' => 'yes'
),
1 =>
array (
'customer_id' => 22,
'test' => 'no',
'is_active' => 'yes'
)
);
$secondKey = array_column($secondArr,'customer_id');
foreach($firstArr as &$value){
$idx2 = array_search($value['customer_id'], $secondKey);
$value = array_merge($value, [
'test' => false !== $idx2 ? $secondArr[$idx2]['test'] : '',
'is_active' => false !== $idx2 ? $secondArr[$idx2]['is_active'] : '',
]);
}
print_r($firstArr);
Output:
Array
(
[0] => Array
(
[customer_id] => 11
[home_delivery] => no
[test] => no
[is_active] => yes
)
[1] => Array
(
[customer_id] => 12
[home_delivery] => no
[test] =>
[is_active] =>
)
[2] => Array
(
[customer_id] => 13
[home_delivery] => no
[test] =>
[is_active] =>
)
)
Sandbox
There are 2 "tricks" I use here, the first, and more important one, is array_column this picks just one column from an array, but the thing is the keys in the resulting array will match the original array. Which we can take advantage of.
The array we get from array column looks like this:
array (
0 => 11,
1 => 22
);
Because the keys match the original array we can use array_search (with the ID) to look up that key, which we can then use in the original array. This gives us an "easier" way to search the second array by flattening it out.
So for example when we look up $firstArr['customer_id'] = 11 in the above array we get the key 0 (which is not boolean false, see below). Then we can take that index and use it for the original array $secondArr and get the values from the other 2 columns.
-Note- that array search returns boolean false when it cant find the item, because PHP treats 0 and false the same we have to do a strict type check !== instead of just !=. Otherwise PHP will confuse the 0 index with being false, which is not something we want.
The second "trick" is use & in the foreach value, this is by reference which allows us to modify the array used in the loop, directly. This is optional as you could just as easily create a new array instead. But I thought I would show it as an option.

PHP Replace Array Values

I have 2 multidimensional arrays that I am working with:
$arr1 =
Array
([type] => characters
[version] => 5.6.7.8
[data] => Array
([Char1] => Array
([id] => 1
[name] =>Char1
[title] =>Example
[tags] => Array
([0] => DPS
[1] => Support))
[Char2] => Array
([id] => 2
[name] =>Char2
[title] =>Example
[tags] => Array
([0] => Tank
[1] => N/A)
)
)
etc...
$arr2=
Array
([games] => Array
([gameId] => 123
[gameType => Match
[char_id] => 1
[stats] => Array
([damage] => 55555
[kills] => 5)
)
([gameId] => 157
[gameType => Match
[char_id] => 2
[stats] => Array
([damage] => 12642
[kills] => 9)
)
etc...
Basically, I need almost all the data in $arr2... but only the Char name from $arr1. How could I merge or add the $arr1['name'] key=>value into $arr2 where $arr1['id'] is equal to $arr2['char_id'] as the "id" field of each array is the same number.
I've attempted using array_merge and array_replace, but I haven't come up with any working solutions. This is also all data that I am receiving from a 3rd party, so I have no control on initial array setup.
Thanks for any help or suggestions!
Actually, this is quite straighforward. (I don't think there a built-in function that does this.)
Loop $arr2 and under it loop also $arr1. While under loop, just add a condition that if both ID's match, add that particular name to $arr2. (And use some referencing & on $arr2)
Consider this example:
// your data
$arr1 = array(
'type' => 'characters',
'version' => '5.6.7.8',
'data' => array(
'Char1' => array(
'id' => 1,
'name' => 'Char1',
'title' => 'Example',
'tags' => array('DPS', 'Support'),
),
'Char2' => array(
'id' => 2,
'name' => 'Char2',
'title' => 'Example',
'tags' => array('Tank', 'N/A'),
),
),
);
$arr2 = array(
'games' => array(
array(
'gameId' => 123,
'gameType' => 'Match',
'char_id' => 1,
'stats' => array('damage' => 55555, 'kills' => 5),
),
array(
'gameId' => 157,
'gameType' => 'Match',
'char_id' => 2,
'stats' => array('damage' => 12642, 'kills' => 9),
),
),
);
foreach($arr2['games'] as &$value) {
$arr2_char_id = $value['char_id'];
// loop and check against the $arr1
foreach($arr1['data'] as $element) {
if($arr2_char_id == $element['id']) {
$value['name'] = $element['name'];
}
}
}
echo '<pre>';
print_r($arr2);
$arr2 should look now like this:
Array
(
[games] => Array
(
[0] => Array
(
[gameId] => 123
[gameType] => Match
[char_id] => 1
[stats] => Array
(
[damage] => 55555
[kills] => 5
)
[name] => Char1 // <-- name
)
[1] => Array
(
[gameId] => 157
[gameType] => Match
[char_id] => 2
[stats] => Array
(
[damage] => 12642
[kills] => 9
)
[name] => Char2 // <-- name
)
)
)
Iterate over $arr2 and add the data to it from the matching $arr1 array value:
$i = 0;
foreach($arr2['games'] as $arr2Game){
$id = $arr2Game['char_id'];
$arr2['games'][$i]['name'] = $arr1['data'][$id]['name'];
$i++;
}
Have not tested this code.
If I'm understanding you correctly, you want to add a name index to each of the arrays within the $arr2['games'] array.
foreach($arr2['games'] as $key => $innerArray)
{
$arr2['games'][$key]['name'] = $arr1['data']['Char'.$innerArray['char_id']]['name'];
}

PHP Multidimensional Arrays - Remove Duplicates

if anyone could please help me here I would be eternally grateful as I've spent about 2 full days now trying to get this to work. I want to take two multidimensional arrays and compare them, then remove any duplicate records.
The scenario is: The values in array2 have already been assigned to a user's profile. The values in array1 are ALL of the available values that the user can choose from. I want to compare the two so that only the ones not already assigned are given as an option (left in the array)...
$array1 = array(
[0] => array( [id] => 3 [name] => Eye Colour )
[1] => array( [id] => 1 [name] => Hair Colour )
[2] => array( [id] => 5 [name] => Hair Length )
[3] => array( [id] => 4 [name] => Height )
);
$array2 = array(
[0] => array( [attribute_id] => 3 [name] => Eye Colour [active] => 1 )
[1] => array( [attribute_id] => 5 [name] => Hair Length [active] => 1 ) )
);
PHP's array_diff() function doesn't work with multidimensional arrays, and I've had a good search around but can't seem to find anything that works for me!
The result based on the above two arrays should be:
$array1 = array(
[0] => array( [id] => 1 [name] => Hair Colour )
[1] => array( [id] => 4 [name] => Height )
);
The [active] field is irrelevant, so I just need it to compare the ID and the Name fields. I realise that the name of the two id fields is different, but it would be a pain to change them as they are database column names.
It needs to completely remove the array, not just the values. I've had issues with previous attempts where it leaves array( ) in there and then this causes issues when I'm looping through the array generating the fields that the user can choose from.
Please help. I will buy you many beers! :)
Thanks,
Steve
I don't know how to do it with any built-in PHP function but here's a custom one:
$array1 = array(
array( 'id' => 3, 'name' => 'Eye Colour' ),
array( 'id' => 1, 'name' => 'Hair Colour' ),
array( 'id' => 5, 'name' => 'Hair Length' ),
array( 'id' => 4, 'name' => 'Height' ),
);
$array2 = array(
array( 'attribute_id' => 3, 'name' => 'Eye Colour', 'active' => 1 ),
array( 'attribute_id' => 5, 'name' => 'Hair Length', 'active' => 1 )
);
// function to remove duplicates
function myArrayDiff($array1, $array2) {
// loop through each item on the first array
foreach ($array1 as $key => $row) {
// loop through array 2 and compare
foreach ($array2 as $key2 => $row2) {
if ($row['id'] == $row2['attribute_id']) {
// if we found a match unset and break out of the loop
unset($array1[$key]);
break;
}
}
}
return array_values($array1);
}
$array3 = myArrayDiff($array1, $array2);
print_r($array3);
/* result:
Array
(
[0] => Array
(
[id] => 1
[name] => Hair Colour
)
[1] => Array
(
[id] => 4
[name] => Height
)
)
*/

Categories