create multimentional array in php - php

I try to create a multimentional array , I have a list of title
$array_title = array(
"fey palin" => 3,
"big theory" => 3,
"nyc through" => 3,
"jonas storm" => 3,
"bang theory" => 3,
"bang big" => 3,
"storm test" => 3,
"plain sahra" => 3,
"mind woolf" => 3,
"mind virginia" => 3
);
and I want to create a subarray if I find a link between two title for example big theory and bang theory are link by the word "theory"
Here my full code :
$array_title = array(
"fey palin" => 3,
"big theory" => 3,
"nyc through" => 3,
"jonas storm" => 3,
"bang theory" => 3,
"bang big" => 3,
"storm test" => 3 ,
"plain sahra" => 3,
"mind woolf" => 3,
"mind virginia" => 3
);
$new_array = array();
$i = 0;
foreach($array_title as $title => $value){
if(count($new_array) > 0){
$words = explode(' ',$title);
if(preg_grep ('/\b('.$words[0].'|'.$words[1].')\b/i', $new_array)){
$result = preg_grep ('/\b('.$words[0].'|'.$words[1].')\b/i', $new_array);
reset($result);
$first_key = key($result);
$new_array[$first_key][] = $title;
}else{
$new_array[$i] = $title;
}
}else{
$new_array[$i] = $title;
}
$i++;
}
it s seems i cant do that
$new_array[$first_key][] = $title;
I have an error which is:
[] operator not supported for strings
Edit : I changed my code a bit but I have some duplicate value
Here is my updated code
$array_title = array("fey palin" => 3 , "big theory" => 3 , "nyc through" => 3 ,
"bang theory" => 3 , "jonas storm" => 3 , "bang big" => 3 ,
"storm test" => 3 , "plain sahra" => 3 ,"mind woolf" => 3, "mind virginia" => 3);
$new_array = array();
foreach($array_title as $title => $value){
$words = explode(' ',$title);
if(count($new_array) > 0){
foreach($new_array as $key => $value){
if(preg_match('/\b('.$words[0].'|'.$words[1].')\b/', $key)){
$new_array[$key][$title] = $title;
}else{
if(count($value) > 0){
foreach($value as $val){
if(preg_match('/\b('.$words[0].'|'.$words[1].')\b/', $val)){
$new_array[$key][$title] = $title;
}
}
}else{
$new_array[$title] = array();
}
}
}
}else{
$new_array[$title] = array();
}
}
and the output:
Array
(
[fey palin] => Array
(
)
[big theory] => Array
(
[bang theory] => bang theory
[bang big] => bang big
)
[nyc through] => Array
(
)
[bang theory] => Array << To remove
(
[bang big] => bang big
)
[jonas storm] => Array
(
[storm test] => storm test
)
[bang big] => Array
(
)
[storm test] => Array << To remove
(
)
[plain sahra] => Array
(
)
[mind woolf] => Array
(
[mind virginia] => mind virginia
)
[mind virginia] => Array
(
)
)

The problem is this line:
$new_array[$i] = $title;
This is setting the initial elements of $new_array to strings, not an array. So when you later do
$new_array[$first_key][] = $title;
it's trying to do array_push on a string.
That line should be:
$new_array[$i] = array($title);

Add this statement before the one that triggers the error:
if (!isset($new_array[$first_key])) $new_array[$first_key] = array();
This way you ensure that $new_array[$first_key] is initialised as an array and you can safely add elements to that array.
But your algorithm will still fail, as you use that same array $new_array in your preg_grep call. That will not work as you want when you have added sub-arrays to $new_array.
You need to two variables: one for doing the preg_grep, which you do not change, and one where you add to in your loop. Currently you are mixing these two...

Related

How to merge two arrays diferents on one

How to update an array of objects, adding the quantities if you already have the same ID, or if you have not created a new object.
I tried to explain in the code with the arrays and also with the idea of how I would like the result to be.
old Array
$a1 = [
array(
"id" => 1,
"qty" => 1
),
array(
"id" => 2,
"qty" => 1
)
];
$a2 = [
array(
"id" => 1,
"qty" => 1
)
];
$output = array_merge($a1, $a2);
echo '<pre>';
print_r($output);
echo '</pre>';
Result Error:
Array
(
[0] => Array
(
[id] => 1
[qty] => 1
)
[1] => Array
(
[id] => 2
[qty] => 1
)
[2] => Array
(
[id] => 1
[qty] => 1
)
)
What I need, in addition to if the ID does not contain, add.
Array
(
[0] => Array
(
[id] => 1
[qty] => 2
)
[1] => Array
(
[id] => 2
[qty] => 1
)
)
You can take the first array as base, then search for the key (if existing) where the product matches the id. Then either add the quantity and recalculate the price or you just add the reformatted element (id to product conversion).
$result = $a;
foreach($b as $element) {
$matchingProductIndex = array_search($element['id'], array_column($a, 'product'));
if ($matchingProductIndex !== false) {
$pricePerUnit = $result[$matchingProductIndex]['price'] / $result[$matchingProductIndex]['qty'];
$result[$matchingProductIndex]['qty'] += $element['qty'];
$result[$matchingProductIndex]['price'] = $result[$matchingProductIndex]['qty'] * $pricePerUnit;
} else {
$result[] = [
'qty' => $element['qty'],
'product' => $element['id'],
'price' => $element['price'],
];
}
}
print_r($result);
Working example.
Loop through both arrays with foreach and check the ids against each other.
https://paiza.io/projects/lnnl5HeJSFIOz_6KD6HRIw
<?php
$arr1 = [['qty' => 4, 'id' => 4],['qty' => 1,'id' => 30]];
$arr2 = [['id' => 30, 'qty' => 19],['id' => 31, 'qty' => 2]];
$arr3 = [];
foreach($arr1 as $iArr1){
$match = false;
foreach($arr2 as $iArr2){
if($iArr1['id'] === $iArr2['id']){
$arr3[] = ['id' => $iArr1['id'], 'qty' => $iArr1['qty'] + $iArr2['qty']];
$match = true;
}
}
if(!$match){
$arr3[] = $iArr1;
$arr3[] = $iArr2;
}
}
print_r($arr3);
?>
One approach could be one I more often suggested.
First lets merge $a2 with one to simplify looping over one larger collection.
If we then create a small mapping from id to its index in the result array we can update the running total of qty.
$map = [];
$result = [];
// Merge the two and do as per usual, create a mapping
// from id to index and update the qty at the corresponding index.
foreach (array_merge($a1, $a2) as $subarr) {
$id = $subarr['id'];
if (!key_exists($id, $map)) {
$index = array_push($result, $subarr) - 1;
$map[$id] = $index;
continue;
}
$result[$map[$id]]['qty'] += $subarr['qty'];
}
echo '<pre>', print_r($result, true), '</pre>';
Output:
Array
(
[0] => Array
(
[id] => 1
[qty] => 2
)
[1] => Array
(
[id] => 2
[qty] => 1
)
)

Sum like values in Multi-Dimensional array php

I need to sum the values in element 1 of my array where the values in element 0 are duplicate.
Here's a small piece of my array
Array
(
[0] => 3
[1] => 1
)
Array
(
[0] => 3
[1] => 2
)
Array
(
[0] => 3
[1] => 128
)
Array
(
[0] => 39
[1] => 4
)
The results i'm expecting to see
Array
(
[0] => 3
[1] => 131
)
Array
(
[0] => 39
[1] => 4
)
I'm still really new to PHP so any help is greatly appreciated.
You can use a combination of array_intersect, array_column and array_sum to only iterate twice. (One for each unique column 0 value).
$col0 = array_column($arr, 0);
$col1 = array_column($arr, 1);
Foreach(array_unique($col0) as $val){
$res[] = [$val, array_sum(array_intersect_key($col1, array_intersect($col0,[$val])))];
}
Var_dump($res);
https://3v4l.org/gKb5b
The way I've done it is made sure all duplicates where put in the same array.
// Your data
$sample = [[3, 1],[3, 2],[3, 128],[39, 4]];
foreach($sample as $array){
$tmp[$array[0]][] = $array[1];
}
# Output: {"3":[1,2,128],"39":[4]}
Now sum the arrays, and put it back to the structure it originally was.
foreach($tmp as $k => $v){
$new[] = [$k, array_sum($v)];
}
# Output: [[3,131],[39,4]]
But many roads lead to Rome.
Try this code. It may help you.
$array = array(["0" => 3, "1" => 1] , ["0" => 3, "1" => 2], ["0" => 3, "1" => 128], ["0" => 39, "1" => 4]);
$finalArray = [];
foreach($array as $a) {
$finalArray[$a[0]][0] = $a[0];
$finalArray[$a[0]][1] = !isset($finalArray[$a[0]][1]) ? $a[1] : $finalArray[$a[0]][1] + $a[1];
}
echo '<pre>';
print_r($finalArray);
exit;
You could do something like this. I have separated into two foreach. Hope it helps.
<?php
$a = [[3,1],[3,2],[3,128],[39,4]];
$result=[];
$temp = [];
foreach($a as $line) {
$temp[$line[0]] += $line[1];
}
foreach($temp as $k => $value) {
$result[]=[$k ,$value];
}
$data =
[
[3,1],
[3,2],
[3,128],
[39,4]
];
foreach($data as $item)
$sums[$item[0]] = ($sums[$item[0]] ?? 0) + $item[1];
$result = array_map(null, array_keys($sums), $sums);
var_export($result);
Output:
array (
0 =>
array (
0 => 3,
1 => 131,
),
1 =>
array (
0 => 39,
1 => 4,
),
)
$arr = [ [ 3, 1],[ 3, 2 ],[ 3, 128], [ 39, 4]];
$sum = [];
foreach($arr as $value) {
$sum[$value[0]][] = $value[1];
}
foreach($sum as $key=>$value ) {
$result[] = [ $key, array_sum($value)];
}
Output:
Array
(
[0] => Array
(
[0] => 3
[1] => 131
)
[1] => Array
(
[0] => 39
[1] => 4
)
)

Check same value in array

I have the following array:
$teams = [["id" => 1, "address" => "A1"],["id" => 2, "address" => "A1"],["id" => 3, "address" => "A2"]];
How can I check and get the teams with the same address? My output should be Team ID 1 and 2? Consider that I cannot use hard coded address. The data is dynamic and is coming from the database.
In php, laravel.
Thank you in advance!
Another way to do this is to use array_column() and array_count_values(). Then use array_filter() to remove elements with no duplicates:
$teams = [
["id" => 1, "address" => "A1"],
["id" => 2, "address" => "A1"] ,
["id" => 3, "address" => "A2"]
];
$dups = array_count_values(array_column($teams, 'address'));
$teams = array_filter($teams, function($item) use($dups) {
return $dups[$item['address']] > 1;
});
print_r($teams);
Outputs (reformatted):
Array
(
[0] => Array([id] => 1, [address] => A1)
[1] => Array([id] => 2, [address] => A1)
)
First you need to group by their address and then you can use array_filter() to truncate your array based on criteria:
<?php
$teams = [["id" => 1, "address" => "A1"],["id" => 2, "address" => "A1"],["id" => 3, "address" => "A2"]];
// Set a new array
$filtered = [];
// Loop the teams
foreach($teams as $v)
{
// Group the teams into their respective addresses
$filtered[$v['address']][] = $v;
}
// Filter out any address with 1 or fewer teams
$filtered = array_filter($filtered, function($v){
return count($v) > 1;
});
print_r($filtered);
// Now you can loop $filtered and display whatever you want
Output:
Array
(
[A1] => Array
(
[0] => Array
(
[id] => 1
[address] => A1
)
[1] => Array
(
[id] => 2
[address] => A1
)
)
)
Go through the array, remember which addresses are used by which team. When there is more than one team stored at a key (address), you found a duplicate:
<?php
$teams = [
["id" => 1, "address" => "A1"]
,["id" => 2, "address" => "A1"]
,["id" => 3, "address" => "A2"]
];
function findDuplicates($teams) {
$addresses = [];
foreach ($teams as $team) {
if (!isset($addresses[$team["address"]])) {
$addresses[$team["address"]] = [];
}
$addresses[$team["address"]][] = $team["id"];
}
foreach ($addresses as $address => $teamsHere) {
if (count($teamsHere) > 1) {
echo "Teams with same address (" . $address . "): " . join(",", $teamsHere) . "\n";
}
}
}
findDuplicates($teams);
Try it online!
Edit: a less "clunky" approach, using array_* functions:
<?php
$teams = [
["id" => 1, "address" => "A1"]
,["id" => 2, "address" => "A1"]
,["id" => 3, "address" => "A2"]
];
function findDuplicates($teams) {
$addresses = array_column($teams, "address");
$counts = array_count_values($addresses);
return array_filter($teams, function($team) use ($counts) { return $counts[$team["address"]] > 1; });
}
print_r(findDuplicates($teams));
Try it online!

Best way to calculate overall records based on associative data

I'm processing the final results of competitions and its general report on the best trainer and which place the trainer should get.
I have already prepared associative arrays below. The key represents trainer's id and the value represents the number of medals in a category (gold, silver, bronze) that his/her athletes got.
[gold] => Array
(
[777777] => 4
[333333] => 2
[555555] => 1
[999999] => 1
)
[silver] => Array
(
[999999] => 3
[777777] => 3
[333333] => 2
)
[bronze] => Array
(
[333333] => 6
[777777] => 4
[999999] => 2
)
Next array associates trainer's id with its name:
[trainers] => Array
(
[333333] => Trainer 4
[777777] => Trainer 1
[999999] => Trainer 2
[555555] => Trainer 3
)
I have stuck processing the data above into final results like this. Any ideas on how it could be done elegantly? The problem is that the data is never constant and the size of the array is always different.
Any help would be greatly appreciated.
Here is code sample:
$gold, $silver, $bronze, $trainers are arrays with information you provided.
$out = [];
foreach($trainers as $trainerId=> $trainerName){
$out[] = array(
'id'=>$trainerId,
'name'=>$trainerName,
'gold'=>isset($gold[$trainerId])?$gold[$trainerId]:0,
'silver'=>isset($silver[$trainerId])?$silver[$trainerId]:0,
'bronze'=>isset($bronze[$trainerId])?$bronze[$trainerId]:0,
);
}
uasort($out, function($a, $b){
// Here: sort by your algorithm. Here is example:
if($a['gold'] != $b['gold']){
return $b['gold'] - $a['gold'];
}
if($a['silver'] != $b['silver']){
return $b['silver'] - $a['silver'];
}
return $b['bronze'] - $a['bronze'];
});
$placeId = 1;
foreach($out as &$info){
$info['place'] = $placeId++;
}
unset($info);
foreach($out as $info){
echo "{$info['place']} place goes to - {$info['name']} ({$info['id']}) as he/she got {$info['gold']} gold medals, {$info['silver']} silver and {$info['bronze']} bronze";
}
Here is another way to do it with metrics:
$gold = array
(
'777777' => 4,
'333333' => 2,
'555555' => 1,
'999999' => 1
);
$silver = array
(
'999999' => 3,
'777777' => 3,
'333333' => 2
);
$bronze = array
(
'333333' => 6,
'777777' => 4,
'999999' => 2
);
$trainers = array
(
'333333' => 'Trainer 4',
'777777' => 'Trainer 1',
'999999' => 'Trainer 2',
'555555' => 'Trainer 3'
);
$metrics = [
'gold' => 3,
'silver'=> 2,
'bronze' => 1];
$results = [];
foreach ($metrics as $arrName => $metric)
{
foreach (${$arrName} as $trainerId => $medals)
{
$results[$trainerId] = ( isset($results[$trainerId]) ) ? $results[$trainerId]+$medals * $metric : $medals * $metric;
}
}
// sorting scores (by value)
arsort($results);
// print scores
var_dump($results);
// print final results
$placeOut = '';
foreach ($results as $trainerId => $score) {
$placeOut .= $trainers[$trainerId].": he/she has ";
foreach ($metrics as $medalName => $metric) {
$placeOut .= (${$medalName}[$trainerId] > 0 ? ${$medalName}[$trainerId] : 0)." ".$medalName.", ";
}
$placeOut .= "\n";
}
echo "<pre>".$placeOut."</pre>";
?>

How can I merge PHP arrays?

I have two arrays of animals (for example).
$array = array(
array(
'id' => 1,
'name' => 'Cat',
),
array(
'id' => 2,
'name' => 'Mouse',
)
);
$array2 = array(
array(
'id' => 2,
'age' => 321,
),
array(
'id' => 1,
'age' => 123,
)
);
How can I merge the two arrays into one by the ID?
#Andy
http://se.php.net/array_merge
That was my first thought but it doesn't quite work - however array_merge_recursive might work - too lazy to check right now.
This does what Erik suggested (id no. as array key) and merges vlaues in $array2 to $results.
$results = array();
foreach($array as $subarray)
{
$results[$subarray['id']] = array('name' => $subarray['name']);
}
foreach($array2 as $subarray)
{
if(array_key_exists($subarray['id'], $results))
{
// Loop through $subarray would go here if you have extra
$results[$subarray['id']]['age'] = $subarray['age'];
}
}
First off, why don't you use the ID as the index (or key, in the mapping-style array that php arrays are imo)?
$array = array(
1 => array(
'name' => 'Cat',
),
2 => array(
'name' => 'Mouse',
)
);
after that you'll have to foreach through one array, performing array_merge on the items of the other:
foreach($array2 as $key=>$value) {
if(!is_array($array[$key])) $array[$key] = $value;
else $array[$key] = array_merge($array[key], $value);
}
Something like that at least. Perhaps there's a better solution?
<?php
$a = array('a' => '1', 'b' => array('t' => '4', 'g' => array('e' => '8')));
$b = array('c' => '3', 'b' => array('0' => '4', 'g' => array('h' => '5', 'v' => '9')));
$c = array_merge_recursive($a, $b);
print_r($c);
?>
array_merge_recursive — Merge two or more arrays recursively
outputs:
Array
(
[a] => 1
[b] => Array
(
[t] => 4
[g] => Array
(
[e] => 8
[h] => 5
[v] => 9
)
[0] => 4
)
[c] => 3
)
#Andy
I've already looked at that and didn't see how it can help merge multidimensional arrays. Maybe you could give an example.
#kevin
That is probably what I will need to do as I think the code below will be very slow.
The actual code is a bit different because I'm using ADOdb (and ODBC for the other query) but I'll make it work and post my own answer.
This works, however I think it will be very slow as it goes through the second loop every time:
foreach($array as &$animal)
{
foreach($array2 as $animal2)
{
if($animal['id'] === $animal2['id'])
{
$animal = array_merge($animal, $animal2);
break;
}
}
}
foreach ($array as $a)
$new_array[$a['id']]['name'] = $a['name'];
foreach ($array2 as $a)
$new_array[$a['id']]['age'] = $a['age'];
and this is result:
[1] => Array
(
[name] => Cat
[age] => 123
)
[2] => Array
(
[name] => Mouse
[age] => 321
)
<?php
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
print_r($result);
?>
With PHP 5.3 you can do this sort of merge with array_replace_recursive()
http://www.php.net/manual/en/function.array-replace-recursive.php
You're resultant array should look like:
Array (
[0] => Array
(
[id] => 2
[name] => Cat
[age] => 321
)
[1] => Array
(
[id] => 1
[name] => Mouse
[age] => 123
)
)
Which is what I think you wanted as a result.
I would rather prefer array_splice over array_merge because of its performance issues, my solution would be:
<?php
array_splice($array1,count($array1),0,$array2);
?>
$new = array();
foreach ($array as $arr) {
$match = false;
foreach ($array2 as $arr2) {
if ($arr['id'] == $arr2['id']) {
$match = true;
$new[] = array_merge($arr, $arr2);
break;
}
}
if ( !$match ) $new[] = $arr;
}

Categories