I have a multidimensional array with some duplicate sub-arrays:
$data = array(
2 => array (
'User' => 'cat',
'File_name' => 'cat.docx',
'Document' => 'Document1',
'Date' => '2017-03-02',
'Pages' => 1
),
3 => array (
'User' => 'dog',
'File_name' => 'dog.docx',
'Document' => 'Document2',
'Date' => '2017-03-02',
'Pages' => 3
),
4 => array (
'User' => 'shark',
'File_name' => 'shark.docx',
'Document' => 'Document3',
'Date' => '2017-03-01',
'Pages' => 5
),
5 => array (
'User' => 'dog',
'File_name' => 'dog.docx',
'Document' => 'Document2',
'Date' => '2017-03-02',
'Pages' => 3
),
6 => array (
'User' => 'dog',
'File_name' => 'dog.docx',
'Document' => 'Document2',
'Date' => '2017-03-02',
'Pages' => 3
),
//...
);
I could recognize which items are duplicated with:
$final = $dupli = array();
foreach ($data as $key => $array ) {
if(!in_array($array, $final)){
$final[$key] = $array;
}
else
{
$dupli[$key] = $array;
}
}
print_r($dupli);
But I would like to know what index was the first subarray (the key of this) found, as a message, for example:
$final = $dupli = array();
foreach ($data as $key => $array ) {
if(!in_array($array, $final)){
$final[$key] = $array;
}
else
{
$dupli[$key] = $array;
echo "Line " . $key . " duplicated row, the original row is: " . $originalkey;
}
}
Output:
Line 5 duplicated row, the original row is: 3
Line 6 duplicated row, the original row is: 3
To find the key that has a specific value, you can use array_search().
So, to fetch the key from the final array, this should do it in your else statement:
$dupli[$key] = $array;
$originalkey = array_search($array, $final);
echo "Line " . $key . " duplicated row, the original row is: " . $originalkey . "\n";
Read more about array_search() in the docs
As Magnus Eriksson said you can use array_search, if you use it instead of in_array in your existing cycle you can do the operation only once per cycle:
$final = $dupli = array();
foreach ($data as $key => $array ) {
if(($originalkey = array_search($array, $final)) === false){
$final[$key] = $array;
}
else
{
$dupli[$key] = $array;
echo "Line " . $key . " duplicated row, the original row is: " . $originalkey;
}
}
Using array_search() along with loop you can simplify your code like below :
foreach($data as $index => $value)
{
$key = array_search($value, $data);
if($key!==false && $key != $index){
printf("Line %d duplicated row, the original row is: %d\n",$index, $key);
}
}
Test results on CLI
Script
akshay#db-3325:/tmp$ cat test.php
<?php
$data = array(
2 => array (
'User' => 'cat',
'File_name' => 'cat.docx',
'Document' => 'Document1',
'Date' => '2017-03-02',
'Pages' => 1
),
3 => array (
'User' => 'dog',
'File_name' => 'dog.docx',
'Document' => 'Document2',
'Date' => '2017-03-02',
'Pages' => 3
),
4 => array (
'User' => 'shark',
'File_name' => 'shark.docx',
'Document' => 'Document3',
'Date' => '2017-03-01',
'Pages' => 5
),
5 => array (
'User' => 'dog',
'File_name' => 'dog.docx',
'Document' => 'Document2',
'Date' => '2017-03-02',
'Pages' => 3
),
6 => array (
'User' => 'dog',
'File_name' => 'dog.docx',
'Document' => 'Document2',
'Date' => '2017-03-02',
'Pages' => 3
),
//...
);
foreach($data as $index => $value)
{
$key = array_search($value, $data);
if($key!==false && $key != $index){
printf("Line %d duplicated row, the original row is: %d\n",$index, $key);
}
}
?>
Output
akshay#db-3325:/tmp$ php test.php
Line 5 duplicated row, the original row is: 3
Line 6 duplicated row, the original row is: 3
Related
I'm trying to get the occurrences of an array taking in count 1 key value, for example:
$newarray[0] = [
'id' => '2',
'date' => '2016-04-22'
];
$newarray[1] = [
'id' => '2',
'date' => '2016-04-13'
];
$newarray[2] = [
'id' => '2',
'date' => '2016-04-12'
];
$newarray[3] = [
'id' => '1',
'date' => '2016-03-11'
];
$newarray[4] = [
'id' => '2',
'date' => '2016-03-05'
];
$newarray[5] = [
'id' => '1',
'date' => '2016-03-01'
];
I want to transform this, to something like this:
Array ( [0] => Array ( [id] => 1 [date] => 2016-03-11 [occurences] => 2 ) [1] => Array ( [id] => 2 [date] => 2016-04-22 [occurences] => 4 ) )
I tried doing this:
$cleanarray;
$newarray2=$newarray;
$newarray;
$k=0;
$num=1;
for($i=0; $i<count($newarray); $i++){
for($j=1; $j<count($newarray2); $j++){
if($newarray2[$j]["id"]==$newarray[$i]["id"]){
$num++;
}
}
$cleanarray[$k] = [
'id' => $newarray[$i]["id"],
'date' => $newarray[$i]["date"],
'occurences' => $num
];
$k++;
$num=0;
}
But a lot of items repeat, with the same occurrences but several times, and in other cases the repeated items (with same id) would have different occurrences, so I don't know what can I do, I know that there is a function of:
$occurences = array_count_values($array);
But it doesn't work in this case, how can I approach to the solution?
I know what are you looking for, but I think this could solve your problems:
$newarray[0] = [
'id' => '2',
'date' => '2016-04-22'
];
$newarray[1] = [
'id' => '2',
'date' => '2016-04-12'
];
$newarray[2] = [
'id' => '2',
'date' => '2016-04-12'
];
$newarray[3] = [
'id' => '1',
'date' => '2016-03-11'
];
$newarray[4] = [
'id' => '2',
'date' => '2016-03-05'
];
$newarray[5] = [
'id' => '1',
'date' => '2016-03-01'
];
foreach($newarray as $key => $value){
if(isset($found[$value['id']][$value['date']])) {
$found[$value['id']][$value['date']]++;
} else {
$found[$value['id']][$value['date']] = 1;
}
}
print_r($found);
this will return something like:-
Array
(
[2] => Array
(
[2016-04-22] => 1
[2016-04-12] => 2
[2016-03-05] => 1
)
[1] => Array
(
[2016-03-11] => 1
[2016-03-01] => 1
)
)
Using temporary keys for this process will be the most performant way. Temporary keys simplify the output array task, requiring less and faster checking. If you wish to sort on id after the result array is generated, the temporary keys allow a simple ksort() call.
Code: (Demo)
$newarray=[
['id' => '2','date' => '2016-04-22'],
['id' => '2','date' => '2016-04-13'],
['id' => '2','date' => '2016-04-12'],
['id' => '1','date' => '2016-03-11'],
['id' => '2','date' => '2016-03-05'],
['id' => '1','date' => '2016-03-01']
];
foreach($newarray as $a){
if(!isset($result[$a['id']])){
$result[$a['id']]=array_merge($a,['occurrences'=>1]); // use id as temp key, preserve first found date
}else{
++$result[$a['id']]['occurrences']; // only update occurrences to preserve date
}
}
ksort($result); // optionally sort on id ASC
var_export(array_values($result)); // remove temporary keys from first level and print to screen
Output:
array (
0 =>
array (
'id' => '1',
'date' => '2016-03-11',
'occurrences' => 2,
),
1 =>
array (
'id' => '2',
'date' => '2016-04-22',
'occurrences' => 4,
),
)
You can do it like below:-
$final_array = array();
foreach($newarray as $arr){
if(!in_array($arr['id'],array_keys($final_array))){
$final_array[$arr['id']] = $arr;
$final_array[$arr['id']]['occurences'] = 1;
}else{
$final_array[$arr['id']]['occurences'] += 1;
}
}
$final_array= array_values($final_array);
print_r($final_array);
Output:- https://eval.in/847242
Note:- if you want final array to be ascending order of id then use usort() function like below:-
function cmpId($a, $b) {
return ($a['id'] - $b['id']);
}
usort($final_array, "cmpId");
print_r($final_array);
Output:- https://eval.in/847245
I have an array of data like this . This array is the result of a database query , I want to get the index of rows and columns . I tried to get the index of each row but nonetheless failed. so, can anyone help me?
Query Result
array(
(int) 0 => array(
'B' => array(
'company' => 'ABC'
),
'User' => array(
'company' => 'abc'
),
(int) 0 => array(
'date_part' => '3',
'jumlah' => null,
'jumbuy' => '50990',
'admin' => '50010'
),
(int) 1 => array(
'date_part' => '4',
'jumlah' => null,
'jumbuy' => '98990',
'admin' => '2010'
)
),
(int) 1 => array(
'B' => array(
'company' => 'BCD'
),
'User' => array(
'company' => 'bcd'
),
(int) 0 => array(
'date_part' => '3',
'jumlah' => null,
'jumbuy' => '65000',
'admin' => '5000'
),
(int) 1 => array(
'date_part' => '4',
'jumlah' => null,
'jumbuy' => '9000',
'admin' => '5000'
)
),
(int) 3 => array(
'B' => array(
'company' => 'CDE'
),
'User' => array(
'company' => 'cde'
),
(int) 0 => array(
'date_part' => '4',
'jumlah' => null,
'jumbuy' => '34566',
'admin' => '2010'
)
)
);
Get Index
for ($row = 0; $row < count($array); $row++) {
for($col = 0; $col < count(.....); $col++ ) {
echo "Baris [row] kolom [colum]"; // output row and column
}
}
The below code will give you all the indexes of this given array.
I checked the given array with the following code in my localhost.
And it gives us all the keys and the values in this array.
Try this
<?php
foreach($array as $arr=>$value )
{
foreach($value as $ar=>$a)
{
echo $ar."<br>";
foreach($a as $res =>$r)
{
echo $res.": ";
echo $r;
echo "<br>";
}
}
}
?>
Use nested foreach for echoes keys:
foreach ($array as $row => $v) {
foreach ($v as $col => $val) {
echo 'row: ' . $row . ', col: ' . $col . '<br>';
}
}
use the following
foreach ($values as $inde => $value) {
foreach ($value as $key => $result) {
echo '['. $inde.'] ---' .$key . '<br>';
}
}
output will be
[0] ---B
[0] ---User
[0] ---0
[0] ---1
[1] ---B
[1] ---User
[1] ---0
[1] ---1
[3] ---B
[3] ---User
[3] ---0
I have two arrays.The first array have an IDs of rows which matches certain rules.
Please note that I do not have access to the SQL server for running queries.
$ids = array (
0 => '13',
1 => '14',
2 => '12',
3 => '83'
);
$groups = array (
0 =>
array (
'id' => '83',
'email' => 'joe'
),
1 =>
array (
'id' => '12',
'name' => 'emily'
),
2 =>
array (
'id' => '13',
'name' => 'leo'
),
3 =>
array (
'id' => '14',
'name' => 'jack'
)
);
I want the second array to be sorted according to the IDs in the first array.The expected result is this :
$groups = array (
0 =>
array (
'id' => '13',
'email' => 'leo'
),
1 =>
array (
'id' => '14',
'name' => 'jack'
),
2 =>
array (
'id' => '12',
'name' => 'emily'
),
3 =>
array (
'id' => '83',
'name' => 'joe'
)
);
Could you guys help me?
thanks!
$flippedIds = array_flip($ids);
$result = array();
foreach ($group as $item) {
$result[$flippedIds[$item['id']]] = $item;
}
This is given your $ids are unique.
Also you might need to throw in a
ksort($result)
Try this.
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
$newArray = array();
for($i=0;$i<count($ids);$i++)
{
$groupKey = recursive_array_search($ids[$i],$groups);
$newArray[] = $groups[$groupKey];
}
print_r($newArray);
If you have access to the code creating $groups, then
$flippedIds = array_flip($ids);
$group[flippedIds[$id]] = array($id,$name);
ksort($group);
Otherwise you could
$flippedIds = array_flip($ids);
foreach $group as $k => $val){
$group[$k] = $group[$flippedIds[$val['id']]][$k][$val];
}
ksort($group);
If the $group array will never have a duplicate id from $ids then the [$k] element can be removed. Otherwise the duplicated values will over write the previous.
$flippedIds = array_flip($ids);
foreach $group as $k => $val){
$group[$k] = $group[$flippedIds[$val['id']]][$val];
}
ksort($group);
I have this Array:
$mergedItems = array(
0 => array(
'id_item' => 'AZ-110'
'amount' => 12
),
1 => array(
'id_item' => 'BZ-110',
'amount' => 13
),
2 => array(
'id_item' => 'BZ-210',
'amount' => 28
),
3 => array(
'id_item' => 'CZ-291',
'amount' => 11
)
);
AND this Array:
$items = array(
0 => array(
'number' => 'AZ-110'
),
1 => array(
'number' => 'BZ-110'
),
2 => array(
'number' => 'CZ-291'
),
3 => array(
'number' => 'BZ-210'
)
);
Now what i want is to order the first array by the id_item Value to match the same order than the 2nd one by its values.
The resulting array has to include all values of the 2nd array AND the belonging amount-value of the first array. The Keys must not be kept!
I can't use array_merge since the 2nd Array has a dynamic amount of more items, so i only want all items from the second Array that are set in the first one.
Does anyone get what i mean? I am searching for a quick and non-dirty way to get this result as expected.
/Edit:
Expected Array:
$detailedItems = array(
0 => array(
'number' => 'AZ-110',
'amount' => 12
),
1 => array(
'number' => 'BZ-110',
'amount' => 13
),
2 => array(
'number' => 'CZ-291',
'amount' => 11
),
3 => array(
'number' => 'BZ-210',
'amount' => 28
)
);
A PHP 5.5 solution:
$itemMap = array_flip(array_column($mergedItems, 'id_item'));
$result = array_map(
function($i) use($itemMap, $mergedItems) {
return $mergedItems[$itemMap[$i['number']]];
},
$items);
print_r($result);
For 5.3 <= PHP < 5.5 you can simply substitute array_map for array_column:
$itemMap = array_flip(array_map(
function($i) { return $i['id_item']; },
$mergedItems));
How it works
The idea is to create a map of item numbers to indexes inside $mergedItems, ie.
[
'AZ-100' => 0,
'BZ-110' => 1,
'BZ-210' => 2,
// etc
]
With this information at hand it's very easy to iterate over $items (so that the result will be ordered based on that array) and pick the appropriate element from $mergedItems to append to the result each time.
$temp = $items;
foreach($temp as &$val)
{
foreach($mergedItems as $item)
{
if($item['id_item'] == $val['number'])
{
$val['amount'] = $item['amount'];
break;
}
}
}
print_r($temp);
There isn't really a "non-dirty" (meaning single line) way to do this as far as I know, but this function should work:
$out = array();
foreach ($mergedItems as $key => $value) {
if (array_key_exists($key, $detailedItems)) { // Make sure it exists to prevent errors
$out[$key] = $detailedItems[$key] + array('amount' => $value['amount']);
} else {
$out[$key] = $value['amount'];
}
}
print_r($out);
You can try following codes:
foreach ($mergedItems as $item) {
$merged[$item['id_item']] = array('amount' => $item['amount']);
}
foreach ($items as $item)
{
$detailedItems[] = array_merge($item, $merged[$item['number']]);
}
Output
var_dump($detailedItems);
array (size=4)
0 =>
array (size=2)
'number' => string 'AZ-110' (length=6)
'amount' => int 12
1 =>
array (size=2)
'number' => string 'BZ-110' (length=6)
'amount' => int 13
2 =>
array (size=2)
'number' => string 'CZ-291' (length=6)
'amount' => int 11
3 =>
array (size=2)
'number' => string 'BZ-210' (length=6)
'amount' => int 28
I have two arrays
$array1 = array(
0 => array(
'user' => 'user0',
'id' => 'id0'
),
1 => array(
'user' => 'user1',
'id' => 'id1'
),
2 => array(
'user' => 'user2',
'id' => 'id2'
)
);
$array2 = array(
0 => array(
'emp' => 'emp0',
'id' => 'id3'
),
1 => array(
'emp' => 'emp1',
'id' => 'id1'
),
2 => array(
'emp' => 'emp2',
'id' => 'id2'
)
);
i need to loop array 2 first an d give input of id from array1 to the array 1 and search whether the value of id1 from arr1 exists in array2
Maybe this could work? (If I understood your question correctly)
$id_arr = array();
$final_arr = array();
checkArray($array1, $id_arr, $final_arr);
checkArray($array2, $id_arr, $final_arr);
function checkArray($arr, &$id_arr, &$final_arr) {
foreach ($arr as $key => $value) {
if (!in_array($value['id'], $id_arr)) {
$id_arr[] = $value['id'];
$final_arr[] = $value;
}
}
}
var_dump($final_arr);