Merging values of nested array - php

As the title says I get array looking something like this:
array (size=376)
0 =>
array (size=3)
'source' => int 0
'target' => int 47
'officers' =>
array (size=1)
0 => string 'PARKER, Thomas, Sir' (length=19)
1 =>
array (size=3)
'source' => int 0
'target' => int 104
'officers' =>
array (size=1)
0 => string 'STEVENS, Anne' (length=13)
2 =>
array (size=3)
'source' => int 0
'target' => int 187
'officers' =>
array (size=1)
0 => string 'PARKER, Thomas, Sir' (length=19)
3 =>
array (size=3)
'source' => int 0
'target' => int 229
'officers' =>
array (size=1)
0 => string 'GROTE, Byron' (length=12)
4 =>
array (size=3)
'source' => int 0
'target' => int 244
'officers' =>
array (size=1)
0 => string 'GROTE, Byron' (length=12)
5 =>
array (size=3)
'source' => int 1
'target' => int 60
'officers' =>
array (size=1)
0 => string 'BASON, John' (length=11)
6 =>
array (size=3)
'source' => int 1
'target' => int 92
'officers' =>
array (size=1)
0 => string 'HAUSER, Wolfhart, Dr' (length=20)
If source and target are the same I want to create 1 value in this array for example
Insteed of this:
5 =>
array (size=3)
'source' => int 1
'target' => int 92
'officers' =>
array (size=1)
0 => string 'BASON, John' (length=11)
6 =>
array (size=3)
'source' => int 1
'target' => int 92
'officers' =>
array (size=1)
0 => string 'HAUSER, Wolfhart, Dr' (length=20)
I would want to get
5 =>
array (size=3)
'source' => int 1
'target' => int 92
'officers' =>
array (size=1)
0 => string 'BASON, John' (length=11)
1 => string 'HAUSER, Wolfhart, Dr' (length=20)
My idea to achieve this:
for ($i = 0; $i < count($edges); $i++) {
for ($j = $i + 1; $j < count($edges); $j++) {
if($edges[$i]['source']==$edges[$j]['source']&&$edges[$i]['target']==$edges[$j]['target']){
foreach( $edges[$j]['officers'] as $officer){
array_push($edges[$i]['officers'], $officer);
}
array_splice($edges, $j,1);
}
}
}
It seems to be merging but only 2 values and it isn't deleting old values so:
I got something like :
66 =>
array (size=3)
'source' => int 24
'target' => int 103
'officers' =>
array (size=2)
0 => string 'GILAURI, Irakli' (length=15)
1 => string 'JANIN, Neil' (length=11)
67 =>
array (size=3)
'source' => int 24
'target' => int 103
'officers' =>
array (size=1)
0 => string 'MORRISON, David' (length=15)
So it merget Gilauri and Janin but didn't add Morrison, David to officers array and also Gilauri, Irakli and Janin, Neil have separate row in this array which shouldn't be added.

Note that array_splice rekeys the array each time it is executed. From the documentation:
Note that numeric keys in input are not preserved.
I.e. array_splice($array, 1, 1) on $array = [0 => 1, 1 => 2, 2 => 3] will result in [0 => 1, 1 => 3].
Thus when you are iterating with a for loop, your index will point one entry further than before for each removed array element.
To remove by index without rekeying, use unset($edges[$j]) instead of the array_splice().
Alternatively use a foreach loop (by reference to operate on the actual loop and not on a copy):
foreach ($edges as $i => &$edge) {
for ($j = $i + 1; $j < count($edges); $j++) {
if ($edge['source'] == $edges[$j]['source'] && $edge['target'] == $edges[$j]['target']) {
foreach ($edges[$j]['officers'] as $officer) {
array_push($edge['officers'], $officer);
}
array_splice($edges, $j, 1);
}
}
}
But I recommend the unset() alternative as it is much faster (array_splice always recreates the array completely).

This is similar to other problems where you can solve this by using a key from the sub-arrays as a key in your merged result. It's just a little different because you need to use more than one key to determine which records should be merged.
I would suggest doing it by just concatenating the two keys.
foreach ($your_array as $item) {
$k = "$item[source].$item[target]";
if (isset($merged[$k])) {
$merged[$k]['officers'] = array_merge($merged[$key]['officers'], $item['officers']);
} else {
$merged[$k] = $item;
}
}
And if you don't like the composite keys, you can do array_values($merged) afterward to get back to plain numeric keys.

Related

How to write a find query with condition in php-mongodb?

I'm having problem with find query in php-monogodb. find() without conditions works fine but when using condition inside find() method it won't give any results. How to solve this issue?
$connection = new Mongo();
$db = $connection->selectDB('db1');
$collection = $db->selectCollection('customers');
$cursor = $collection->find(array('CUSTOMER_ID' => $id));
$num_docs = $cursor->count();
if($num_docs > 0)
{
foreach($cursor as $obj)
{
echo 'Customer-Id: '.$obj['CUSTOMER_ID']."\n";
echo 'Customer Name: '.$obj['CUST_FIRST_NAME']." ".$obj['CUST_LAST_NAME']."\n";
echo 'Customer Email: '.$obj['CUST_EMAIL']."\n";
echo "\n\n\n";
}
}
After var_dump($cursor->explain()); it prints:
array (size=3)
'queryPlanner' =>
array (size=6)
'plannerVersion' => int 1
'namespace' => string 'db1.customers' (length=13)
'indexFilterSet' => boolean false
'parsedQuery' =>
array (size=1)
'CUSTOMER_ID' =>
array (size=1)
...
'winningPlan' =>
array (size=3)
'stage' => string 'COLLSCAN' (length=8)
'filter' =>
array (size=1)
...
'direction' => string 'forward' (length=7)
'rejectedPlans' =>
array (size=0)
empty
'executionStats' =>
array (size=7)
'executionSuccess' => boolean true
'nReturned' => int 0
'executionTimeMillis' => int 1
'totalKeysExamined' => int 0
'totalDocsExamined' => int 325
'executionStages' =>
array (size=14)
'stage' => string 'COLLSCAN' (length=8)
'filter' =>
array (size=1)
...
'nReturned' => int 0
'executionTimeMillisEstimate' => int 0
'works' => int 327
'advanced' => int 0
'needTime' => int 326
'needYield' => int 0
'saveState' => int 2
'restoreState' => int 2
'isEOF' => int 1
'invalidates' => int 0
'direction' => string 'forward' (length=7)
'docsExamined' => int 325
'allPlansExecution' =>
array (size=0)
empty
'serverInfo' =>
array (size=4)
'host' => string 'deadpool' (length=8)
'port' => int 27017
'version' => string '3.2.4' (length=5)
'gitVersion' => string 'e2ee9ffcf9f5a94fad76802e28cc978718bb7a30' (length=40)
Can you explain what is going wrong?
$cursor = $collection->find(array('CUSTOMER_ID' => $id)); where are you getting the id value from.
and try not using id as sometimes it has issues finding the value esp if $id is used elsewhere.

Argument 2 passed to array_sort() must be callable, string given

I have the following arrays:
array (size=3)
0 =>
array (size=3)
'id' => int 18
'class' => string 'VIP' (length=3)
'fee' => float 20
1 =>
array (size=3)
'id' => int 19
'class' => string 'VVIP' (length=4)
'fee' => float 50
2 =>
array (size=3)
'id' => int 20
'class' => string 'STANDARD' (length=8)
'fee' => float 5
array (size=3)
0 =>
array (size=3)
'id' => int 19
'class' => string 'VVIP' (length=4)
'fee' => int 50
1 =>
array (size=3)
'id' => int 18
'class' => string 'VIP' (length=3)
'fee' => int 20
2 =>
array (size=3)
'id' => int 20
'class' => string 'STANDARD' (length=8)
'fee' => int 5
Now i am trying to sort them both using array_sort in ascending order using the id.:
$array_1 = array_sort($array_1, 'id', SORT_ASC);
$array_2 = array_sort($array_2, 'id', SORT_ASC);
However i keep getting the following error:
Argument 2 passed to array_sort() must be callable, string given
The second parameter of array_sort should be a closure, not a string:
$array_1 = array_sort( $array_1, function($value){
return $value['id'];
});

PHP - Multimentional array - If same value in array, change all values except first

I'm trying to change values of an array if one of the value is several times into and change by null the duplicate values exept the first.
I have this array:
$array =
array (size=6)
0 =>
array (size=3)
'id' => int 1
'data-time-start' => int 0
'data-time-end' => int 5
1 =>
array (size=3)
'id' => int 2
'data-time-start' => int 6
'data-time-end' => int 10
2 =>
array (size=3)
'id' => int 1
'data-time-start' => int 11
'data-time-end' => int 15
3 =>
array (size=3)
'id' => int 3
'data-time-start' => int 16
'data-time-end' => int 20
4 =>
array (size=3)
'id' => int 4
'data-time-start' => int 21
'data-time-end' => int 25
5 =>
array (size=3)
'id' => int 3
'data-time-start' => int 30
'data-time-end' => int 35
6 =>
array (size=3)
'id' => null
'data-time-start' => int 40
'data-time-end' => int 45
7 =>
array (size=3)
'id' => int 3
'data-time-start' => int 45
'data-time-end' => int 60
In this example I have two times 'id' = int 1 and three times 'id' = int 3 . What I would like to do is to keep the first ID but set other duplicate IDs to NULL and return an array like this:
array (size=6)
0 =>
array (size=3)
'id' => int 1
'data-time-start' => int 0
'data-time-end' => int 5
1 =>
array (size=3)
'id' => int 2
'data-time-start' => int 6
'data-time-end' => int 10
2 =>
array (size=3)
'id' => null
'data-time-start' => int 11
'data-time-end' => int 15
3 =>
array (size=3)
'id' => int 3
'data-time-start' => int 16
'data-time-end' => int 20
4 =>
array (size=3)
'id' => int 4
'data-time-start' => int 21
'data-time-end' => int 25
5 =>
array (size=3)
'id' => null
'data-time-start' => int 30
'data-time-end' => int 35
6 =>
array (size=3)
'id' => null
'data-time-start' => int 40
'data-time-end' => int 45
7 =>
array (size=3)
'id' => null
'data-time-start' => int 45
'data-time-end' => int 60
Tried with that but nothing happened...
var_dump(setNulForDuplicatesInArray($array, 'id'))
function setNulForDuplicatesInArray($arr, $keyToFind)
{
$newArr = array();
for ($i = 0; $i < sizeof($arr); $i++) {
if (in_array($arr[$i], $newArr))
$newArr[$i][$keyToFind] = null;
else
$newArr[] = $arr[$i];
}
return $newArr;
}
array() is the same...
Thanks !
One way is to create another container that will be used for checking if that particular ID has already been taken. In every iteration, you'll have to check it. If it has been already inside the container, then set that id to null. Rough example:
$temp = array(); // temporary container
foreach($array as &$a) {
if(!isset($temp[$a['id']])) { // if this id isn't here yet
$temp[$a['id']] = $a; // push it inside
} else {
$a['id'] = null; // if its already taken, set it to null
}
}
Sample Output

How to add to an array in a loop

I’m trying to add to an array in a loop but only the first element in the loop is added.
The array
array (size=7)
0 =>
array (size=2)
'id' => int 1
'name' => string 'john' (length=11)
1 =>
array (size=2)
'id' => int 2
'name' => string 'adam' (length=13)
2 =>
array (size=2)
'id' => int 3
'name' => string 'mary' (length=11)
My loop
foreach ($loops as $key => $loop) {
$idArray['id'] = $loop['id'];
}
var_dump($idArray); die();
Did I do anything wrong?
You overwrite your old value by assigning the new value to the array. An array can't have identical keys.
Try this:
foreach ($loops as $key => $loop)
{
$idArray['id'][] = $loop['id'];
}
var_dump($idArray); die();
So you add items to an array inside your array.
If you want the ordinal values of the $idarray to be the primary key values of what you are iterating over you can do this.
$loops = array(array('id' => 1, 'name' => 'john'), /* ... */);
foreach ($loops as $key => $loop)
{
$idArray[$loop['id']] = $loop;
}
var_dump($idArray); die();
var_dump will reveal this structure
array (size=7)
1 =>
array (size=2)
'id' => int 1
'name' => string 'john' (length=4)
2 =>
array (size=2)
'id' => int 2
'name' => string 'adam' (length=4)
3 =>
array (size=2)
'id' => int 3
'name' => string 'mary' (length=4)

PHP rebuild a big array

array (size=10)
'image' =>
array (size=3)
0 => string 'BlackLingerie(42).jpg' (length=21)
1 => string 'BlackLingerie(43).jpg' (length=21)
2 => string 'BlackLingerie(44).jpg' (length=21)
'text' =>
array (size=3)
0 => string '' (length=0)
1 => string '' (length=0)
2 => string '' (length=0)
'author' =>
array (size=3)
0 => string '' (length=0)
1 => string '' (length=0)
2 => string '' (length=0)
'date' =>
array (size=3)
0 => string '' (length=0)
1 => string '' (length=0)
2 => string '' (length=0)
'verImage' =>
array (size=3)
0 => string 'upload' (length=6)
1 => string 'upload' (length=6)
2 => string 'upload' (length=6)
'imagePicsPath' =>
array (size=3)
0 => string 'http://127.0.0.1/develop/mvc/public/images/pics/BlackLingerie(42).jpg'/' (length=77)
1 => string 'http://127.0.0.1/develop/mvc/public/images/pics/BlackLingerie(43).jpg'/' (length=77)
2 => string 'http://127.0.0.1/develop/mvc/public/images/pics/BlackLingerie(44).jpg'/' (length=77)
'imageThumbPath' =>
array (size=3)
0 => string 'http://127.0.0.1/develop/mvc/public/images/thumbs/BlackLingerie(42).jpg'/' (length=79)
1 => string 'http://127.0.0.1/develop/mvc/public/images/thumbs/BlackLingerie(43).jpg'/' (length=79)
2 => string 'http://127.0.0.1/develop/mvc/public/images/thumbs/BlackLingerie(44).jpg'/' (length=79)
'imagePath' =>
array (size=3)
0 => string 'http://127.0.0.1/develop/mvc/public/images/pics/BlackLingerie(42).jpg'/' (length=77)
1 => string 'http://127.0.0.1/develop/mvc/public/images/pics/BlackLingerie(43).jpg'/' (length=77)
2 => string 'http://127.0.0.1/develop/mvc/public/images/pics/BlackLingerie(44).jpg'/' (length=77)
'imageID' =>
array (size=3)
0 => string '0' (length=1)
1 => string '1' (length=1)
2 => string '2' (length=1)
'submitUploadImages' => string 'Ladda upp bilder till databas' (length=29)
Want to rebuild this array to an more useful array. Like this
array
( [image0] (
'name' =>
'text' =>
'author' =>
'date' =>
'verImage' =>
'imagePicsPath' =>
'imageThumbPath' =>
'imagePath' =>
'imageID' =>
)
[image1] (
'name' =>
'text' =>
'author' =>
'date' =>
'verImage' =>
'imagePicsPath' =>
'imageThumbPath' =>
'imagePath' =>
'imageID' =>
)
And so on depending on how many pictures there is, the keys inside the image array holds the values for each image. Like name, path so on. The incoming array is a $_POST that holds multiple form input data. Need some help to crack this one guys. Need to iterate trough the $_POST array, get the contents and transform to a new array ?
I want unique image arrays that holds the image information before doing my stuff with the database =)
I haven't tested this but it should work:
$incomingArray = $_POST['array'];
$sortedArray = array();
for($i = 0; $i < count($incomingArray); $i++){
foreach($incomingArray as $key => $value){
$sortedArray["image".$i][$key] = $value[i];
}
}
Doing it this way means you don't have to write $sortedArray["image".$i]['NAME'] = $incomingArray['NAME'][$i] for each image value (name, test, author etc.).
Try
foreach( $array as $1st_level_key => $1st_level_value ) {
foreach ( $1st_level_value as $2nd_level_key => $2nd_level_value ) {
$new_array['image'.$2nd_level_key][$1st_level_key] = $2nd_level_value;
}
}
Short answer yes, pretty much like this:
for($i = 0; $i < count($YourArray); $i++)
{
$NewArray["image".$i]["name"] = $YourArray["name"][$i];
...
}

Categories