PHP array last entries of all duplicate records - php

I need to get the last entries of all duplicate records in an array. How can I do this in php
example data
Input Array
Array
(
[0] => Array ( [0] => A )
[1] => Array ( [0] => A )
[2] => Array ( [0] => B )
[3] => Array ( [0] => C )
[4] => Array ( [0] => C )
[5] => Array ( [0] => D )
[6] => Array ( [0] => F )
[7] => Array ( [0] => F )
)
Result output List 1 should only contain last entry of all duplicate records
Array
(
[1] => Array ( [0] => A )
[4] => Array ( [0] => C )
[7] => Array ( [0] => F )
)
Result output List 2 Should contain all other enteries.
Array
(
[0] => Array ( [0] => A )
[2] => Array ( [0] => B )
[3] => Array ( [0] => C )
[5] => Array ( [0] => D )
[6] => Array ( [0] => F )
)

Not sure if you wanted it this way, but you can try this:
<?php
$array = array
(
0 => array ( 0 => 'A' ),
1 => array ( 0 => 'A' ),
2 => array ( 0 => 'B' ),
3 => array ( 0 => 'C' ),
4 => array ( 0 => 'C' ),
5 => array ( 0 => 'D' ),
6 => array ( 0 => 'F' ),
7 => array ( 0 => 'F' )
);
foreach ($array as $k => $v){
echo $k . " --> ";
if (is_array($v)){
foreach($v as $k1=>$v1){
echo $v1."<br />";
$new_array[$k]=$v1;
}
}else{
echo $v."<br />";
}
}
echo "<br />";
// Restructured array
print_r($new_array);
echo "<br />";
// Duplicates
print_r(get_duplicates($new_array));
echo "<br />";
// All entries
print_r(array_unique($new_array));
// Function to get duplicates
function get_duplicates( $array ) {
return array_unique( array_diff_assoc( $array, array_unique( $array ) ) );
}
?>
output would be:
//original
Array ( [0] => A [1] => A [2] => B [3] => C [4] => C [5] => D [6] => F [7] => F )
//dupes
Array ( [1] => A [4] => C [7] => F )
//all entries
Array ( [0] => A [2] => B [3] => C [5] => D [6] => F )

typed this up quickly. haven't had a chance to test it yet, but should do the trick.
note that the inner loop is non-optimal -- it could be improved a lot, especially if the data is known to be sorted (as in the example data), but you didn't specify that, so I haven't assumed it.
<?php
$output_dups = array();
$output_remainder = array();
foreach($input_array as $key=>$data) {
$dup_found = false;
foreach($input_array as $key2=>$data2) {
if($key < $key2 && $data===$data2) { $dup_found = true; }
}
if($dup_found) { $output_dups[] = $data; } else { $output_remainder[] = $data; }
}
?>

//My implementation is something like this.
set_time_limit (1500) ;
ini_set("memory_limit","128M");
$fileName = "_one";
$objScan = new scanCSV();
$objScan->setCSVFileName($fileName);
$objScan->loadCsvFile();
$objScan->separateDuplicateFromUniq();
$objScan->process();
class scanCSV
{
private $_csvFile = NULL;
private $_arrayListAll = NULL;
private $_allDuplicateRec = NULL;
private $_uniqueRec = NULL;
function setCSVFileName($fileName){
$this->_csvFile = $fileName;
}
//-----------------------------------------------------------------------
function loadCsvFile()
{
$arrayListAll = array();
if (($handle = fopen($this->_csvFile . ".csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$arrayListAll[] = $data;
}
}
$this->_arrayListAll = $arrayListAll;
}
//-----------------------------------------------------------------------
public function separateDuplicateFromUniq(){
$allDuplicateRec = array();
$uniqueRec = array();
foreach($this->_arrayListAll as $data){
if ($this->getcount($this->_arrayListAll, $data) > 1)
$allDuplicateRec[] = $data;
else
$uniqueRec[] = $data;
}
$this->_allDuplicateRec = $allDuplicateRec;
$this->_uniqueRec = $uniqueRec;
}
//-----------------------------------------------------------------------
public function process (){
$uniq = $this->removeDuplicate ($this->_allDuplicateRec);
$this->writeCSVFile ($this->_csvFile . "A.csv", $uniq);
$restofEntries = $this->removeLastEntries ($this->_arrayListAll, $uniq);
$this->writeCSVFile ($this->_csvFile . "B.csv", $restofEntries);
}
//-----------------------------------------------------------------------
function removeDuplicate ($allDuplicateRec)
{
foreach ($allDuplicateRec as $k => $v)
if ( $this->getcount($allDuplicateRec, $v) > 1 )
unset($allDuplicateRec[$k]);
return $allDuplicateRec;
}
//-----------------------------------------------------------------------
function removeLastEntries ($arrayListAll, $uniq){
foreach ($uniq as $entry)
if(in_array($entry, $arrayListAll))
unset($arrayListAll[array_search($entry, $arrayListAll)]);
return $arrayListAll;
}
//-----------------------------------------------------------------------
function getcount($arrayList1, $data){
$address = $data[2];
$count =0;
foreach ($arrayList1 as $dt)
if ($address == $dt[2])
$count++;
return $count;
}
//-----------------------------------------------------------------------
function writeCSVFile ($fileName, $data){
$fp = fopen($fileName, 'w');
foreach ($data as $k=>$fields)
fputcsv($fp, $fields);
fclose($fp);
}
//-----------------------------------------------------------------------
} // end of scan Optimized

Related

multidimensional array store each list array inside another array

I have nested multidimensional arrays that may be 2 or 3 levels deep. Inside it I may or may not have list arrray. I need to loop over the array:
Array
(
[0] => Array
(
[id] => 1
[name] => cat_name_1
[list] => Array
(
[1] => swgdgbdg
[2] => xcbcxb
)
)
[1] => Array
(
[id] => 3
[name] => cat_name_3
[list] => Array
(
[0] => Array
(
[id] => 1
[name] => cat_name_1
[list] => Array
(
[1] => 543h54h
[2] => 54hrhhfr2
)
)
[1] => Array
(
[id] => 2
[name] => cat_name_2
[list] => Array
(
[1] => eherfherh
[2] => 4564642
)
)
[2] => Array
(
[1] => erggb45yt
[2] => jyuk768k
)
[3] => Array
(
[1] => sdgsdgsdg
[2] => 4tg34g34g
)
)
)
and store the following in another array:
array (
0 => array (
[1] => swgdgbdg
[2] => xcbcxb
) ,
1 => array(
[1] => 543h54h
[2] => 54hrhhfr2
) ,
2 => array(
[1] => eherfherh
[2] => 4564642
),
3 => array(
[1] => erggb45yt
[2] => jyuk768k
),
4 => array(
[1] => sdgsdgsdg
[2] => 4tg34g34g
)
);
You can use array_walk_recursive() to get the key 1,2 and are not array element, like this, check the live demo here.
$result = [];
$temp = [];
array_walk_recursive($array, function($v, $k) use(&$result, &$temp){
if($k == 1)
$temp[$k] = $v;
if($k == 2)
{
$temp[$k] = $v;
$result[] = $temp;
}
});
print_r($result);
Edit for unfixed length and unordered index, live demo.
Extend the array_walk_recursive() with a third parameter for the callfunction to indicate if it's at the start of an subarray.
$result = [];
$temp = [];
$length = 0;
uarray_walk_recursive($array, function($v, $k, $f) use(&$result, &$temp, &$length){
if(is_numeric($k)) {
if($f && $length != 0) {
$result[] = $temp;
$length = 0;
$temp = [];
}
$temp[$k] = $v;
$length++;
}
});
$result[] = $temp;
print_r($result);
function uarray_walk_recursive(&$input, $funcname)
{
if (!is_callable($funcname)) {
if (is_array($funcname)) {
$funcname = $funcname[0] . '::' . $funcname[1];
}
user_error('uarray_walk_recursive() Not a valid callback ' . $user_func,
E_USER_WARNING);
return;
}
if (!is_array($input)) {
user_error('uarray_walk_recursive() The argument should be an array',
E_USER_WARNING);
return;
}
$args = func_get_args();
$flag = true;
foreach ($input as $key => $item) {
if (is_array($item)) {
$args[2] = false;
$flag = true;
uarray_walk_recursive($item, $funcname, $args);
$input[$key] = $item;
} else {
$args[2] = $flag;
$flag = false;
$args[0] = &$item;
$args[1] = &$key;
call_user_func_array($funcname, $args);
$input[$key] = $item;
}
}
}
PseudoCode
function getSomething(var arr)
{
flag = 0;
output = []
for( i = 0 to arr.length)
{
check arr[i] is array,
if yes,then flag = 1 and output.add(getSomething(arr[i]))
if not, continue
}
if flag =0,then return arr
else return output;
}

Group and merge array row data based on one column

I have an array a bit like:
Array (
[1] => Array
(
[1] => 21
[2] => 3
[0] => Analyst
)
[2] => Array
(
[1] => 47
[2] => 8
[0] => Catalysis
)
[3] => Array
(
[1] => 1
[2] => 0
[0] => Biomaterials
)
[4] => Array
(
[3] => 12
[4] => 2
[0] => Analyst
)
[5] => Array
(
[5] => 12
[6] => 2
[0] => Analyst
)
...
However I would like to renumber those entries with the same [0] value so that I end up with
[1] => Array
(
[1] => 21
[2] => 3
[3] => 12
[4] => 2
[5] => 12
[6] => 2
[0] => Analyst
)
So far I've tried getting the [0] values out of the $results array by putting them in their own array and saying if you're already there then add [3] and [4] to where [1] and [2] are in a new array but it's not working.
$final = array();
$jArray = array();
foreach($results as $key => $result) {
if(!in_array($result[0],$jArray) && !empty($result[0])) {
$jArray[$i] = $result[0];
$i++;
}
}
for($x = 0; $x < count($results); $x++) {
$k = array_search($results[$x][0],$jArray);
if(!isset($results[$x][1]))
$final[$k][1] = $results[$x][1];
if(!isset($results[$x][2]))
$final[$k][2] = $results[$x][2];
if(!isset($results[$x][3]))
$final[$k][3] = $results[$x][3];
if(!isset($results[$x][4]))
$final[$k][4] = $results[$x][4];
if(!isset($results[$x][5]))
$final[$k][5] = $results[$x][5];
if(!isset($results[$x][6]))
$final[$k][6] = $results[$x][6];
}
Any simpler ways of doing this?
You can do this way...
$new_arr=array();
$arkeys = array_unique(array_map(function ($v){ return $v[0];},$arr));
foreach($arr as $k=>$arr1)
{
$new_arr[$arr1[0]][]=array_slice($arr1,0,count($arr1)-1);
}
foreach($arkeys as $v)
{
$new_arr[$v] = call_user_func_array('array_merge', $new_arr[$v]);
}
print_r($new_arr);
OUTPUT :
Array
(
[Analyst] => Array
(
[0] => 21
[1] => 3
[2] => 12
[3] => 2
[4] => 12
[5] => 2
)
[Catalysis] => Array
(
[0] => 47
[1] => 8
)
[Biomaterials] => Array
(
[0] => 1
[1] => 0
)
)
Working Demo
If you just want to group by the first element of the sub array, a single loop is enough:
$result = array();
foreach ($array as $sub_arr) {
$key = $sub_arr[0];
unset($sub_arr[0]);
if (!isset($result[$key])) {
$result[$key] = array();
}
$result[$key] += $sub_arr;
}
Here
$final = array();
foreach($results as $key => $result) {
if (!in_array($result[0], array_keys( $final ) ) && !empty($result[0])) {
$final[$result[0]] = array( $result[0] );
}
foreach($result as $k => $v) {
if ($k != 0 && isset($v)) {
$final[$result[0]][$k] = $v;
}
}
}

Array not filling out like I'm expecting it to

I have a function that's supposed to take in an array of arrays, and split it into an array of arrays of 100 items each. The problem is that when I execute it, in this case, passing it 1137 items, the return array, has 12 arrays, all empty except for the last one.
Here's the code:
$names_to_fetch_from_twitter = array (
array('screen_name' => 'acme', 'profiles_rownum' => 1, 'screen_name_rownum' => 1),
array('screen_name' => 'acme1', 'profiles_rownum' => 2, 'screen_name_rownum' => 2),
array('screen_name' => 'acme2', 'profiles_rownum' => 3, 'screen_name_rownum' => 3),
array('screen_name' => 'acme3', 'profiles_rownum' => 4, 'screen_name_rownum' => 4),
array('screen_name' => 'acme4', 'profiles_rownum' => 5, 'screen_name_rownum' => 5)
);
$names_to_fetch_from_twitter_organized = split_into_blokcs_of_3 ($names_to_fetch_from_twitter);
echo '<pre>';
print_r($names_to_fetch_from_twitter_organized);
echo '</pre>';
function split_into_blokcs_of_3 ($names_to_fetch_from_twitter)
{
$names_to_fetch_from_twitter_organized = array();
$count = 1;
$screen_names = array();
$profiles_row_nums = array();
$screen_name_rownums = array();
foreach ($names_to_fetch_from_twitter as $name_to_fetch_from_twitter) {
$screen_names[] = $name_to_fetch_from_twitter['screen_name'];
$profiles_row_nums[] = $name_to_fetch_from_twitter['profiles_rownum'];
$screen_name_rownums[] = $name_to_fetch_from_twitter['screen_name_rownum'];
$count++;
if ($count > 3) {
$count = 1;
$screen_names = array();
$profiles_row_nums = array();
$screen_name_rownums = array();
$names_to_fetch_from_twitter_organized[] =
package_into_array($screen_names,$profiles_row_nums,$screen_name_rownums,$names_to_fetch_from_twitter_organized);
}
}
if ($count > 1) {
$names_to_fetch_from_twitter_organized[] =
package_into_array($screen_names,$profiles_row_nums,$screen_name_rownums,$names_to_fetch_from_twitter_organized);
}
return $names_to_fetch_from_twitter_organized;
}
function package_into_array($screen_names,$profiles_row_nums,$screen_name_rownums,$names_to_fetch_from_twitter_organized)
{
$names_to_fetch_from_twitter_organized[] = array (
'screen_names' => implode (',',$screen_names),
'profiles_row_nums' => $profiles_row_nums,
'screen_name_rownums' => $screen_name_rownums
);
return $names_to_fetch_from_twitter_organized;
}
Here's the output:
Array
(
[0] => Array
(
[0] => Array
(
[screen_names] =>
[profiles_row_nums] => Array
(
)
[screen_name_rownums] => Array
(
)
)
)
[1] => Array
(
[0] => Array
(
[0] => Array
(
[screen_names] =>
[profiles_row_nums] => Array
(
)
[screen_name_rownums] => Array
(
)
)
)
[1] => Array
(
[screen_names] => acme3,acme4
[profiles_row_nums] => Array
(
[0] => 4
[1] => 5
)
[screen_name_rownums] => Array
(
[0] => 4
[1] => 5
)
)
)
)
When I'm expecting the following:
Array
(
[0] => Array
(
[screen_names] => acme1,acme2,acme3
[profiles_row_nums] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[screen_name_rownums] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
)
[1] => Array
(
[screen_names] => acme4,acme5
[profiles_row_nums] => Array
(
[0] => 1
[1] => 2
)
[screen_name_rownums] => Array
(
[0] => 1
[1] => 2
)
)
)
Any ideas?
Solution:
I had a couple of errors:
I was resetting the arrays before I included them in the master array
I was incrementing the array both in the main function and the helper function.
Here's the correct code:
function split_into_blokcs_of_3 ($names_to_fetch_from_twitter)
{
$names_to_fetch_from_twitter_organized = array();
$count = 1;
$screen_names = array();
$profiles_row_nums = array();
$screen_name_rownums = array();
foreach ($names_to_fetch_from_twitter as $name_to_fetch_from_twitter) {
$screen_names[] = $name_to_fetch_from_twitter['screen_name'];
$profiles_row_nums[] = $name_to_fetch_from_twitter['profiles_rownum'];
$screen_name_rownums[] = $name_to_fetch_from_twitter['screen_name_rownum'];
$count++;
if ($count > 3) {
$names_to_fetch_from_twitter_organized =
package_into_array($screen_names,$profiles_row_nums,$screen_name_rownums,$names_to_fetch_from_twitter_organized);
$count = 1;
$screen_names = array();
$profiles_row_nums = array();
$screen_name_rownums = array();
}
}
if ($count > 1) {
$names_to_fetch_from_twitter_organized =
package_into_array($screen_names,$profiles_row_nums,$screen_name_rownums,$names_to_fetch_from_twitter_organized);
}
return $names_to_fetch_from_twitter_organized;
}
I think you might be assuming that a new array is created inside of the if($count > 3) block.
You might try adding new array() there instead of just array but that should overwrite what was there previously.

Arrange PHP Multidimensional Array By Inner Index

How to arrange this array by last inner index ( 0, 1, 2 ) and get the value of the last inner index as the value of each second index:
Array
(
[text] => Array
(
[grid] => Array
(
[0] => 3
[1] => 4
[2] => 5
)
[image] => Array
(
[0] =>
[1] =>
[2] =>
)
[align] => Array
(
[0] => left
[1] => right
[2] => left
)
[title] => Array
(
[0] =>
[1] =>
[2] =>
)
[content] => Array
(
[0] =>
[1] =>
[2] =>
)
)
)
And have the results as below:
Array
(
[text] => Array
(
[0] => Array
(
[grid] => 3
[image] =>
[align] => left
[title] =>
[content] =>
)
[1] => Array
(
[grid] => 4
[image] =>
[align] => right
[title] =>
[content] =>
)
[2] => Array
(
[grid] => 5
[image] =>
[align] => left
[title] =>
[content] =>
)
)
)
This will do the work
function restructure($arr){
$newArr = array();
foreach($arr as $k => $v){
foreach($v as $k1 => $v1){
foreach($v1 as $k2 => $v2){
$newArr[$k][$k2][$k1] = $v2;
}
}
}
return $newArr;
}
As SiGanteng suggested, i dont see other ways than a for/foreach loop:
function buildArray($source, $key = false)
{
// Build the new array
$new_array = array();
// Define groups
$groups = $key === false ? array_keys($source) : array($key);
foreach($groups AS $group)
{
// Get the keys
$keys = array_keys($array[$group]);
// Count the values
$num_entries = count($array[$group][$keys[0]]);
for($i = 0; $i < $num_entries; $i++)
{
foreach($keys AS $key)
{
$new_array[$group][$i][$key] = $array[$group][$key][$i];
}
}
}
return $new_array;
}
This allow you to define the key you need to build; If not specified, the function build the array for every key.
This should work.
function formatit($arr) {
$new = array();
foreach($arr as $k=>$v) {
foreach($v as $k1=>$v1) {
$new[$k1][$k] = $v1;
}
}
return $new;
}
Tested. Call it as
$arr['text'] = formatit($arr['text']);
http://ideone.com/rPzuR

PHP: Modifying array recursively?

I have tried to make a function that iterates through the following array to flatten it and add parent id to children, where applicable. I just can't make it work, so I hope that anyone here has an idea of what to do:
Here's the starting point:
Array
(
[0] => Array (
[id] => 1
[children] => array (
[id] => 2
[children] => Array (
[0] => Array (
[id] => 3
)
)
)
)
The expected result :
Array (
[0] => array (
[id] => 1
)
[1] => array (
[id] => 2
)
[2] => array (
[id] => 3,
[parent] => 2
)
)
Hope that anyone can point me in the right direction. Thanks a lot!
Solution (Thanks to Oli!):
$output = array();
function dejigg($in) {
global $output;
if (!isset($in['children'])) {
$in['children'] = array();
}
$kids = $in['children'] or array();
unset($in['children']);
if (!isset($in['parent'])) {
$in['parent'] = 0; // Not neccessary but makes the top node's parent 0.
}
$output[] = $in;
foreach ($kids as $child) {
$child['parent'] = $in['id'];
dejigg($child); // recurse
}
return $output;
}
foreach ($array as $parent) {
$output[] = dejigg($parent);
}
$array = $output;
print("<pre>".print_r($array,true)."</pre>");
I've tested it this time. This does work!
$input = array( array('id' => 1, 'children'=>array( array('id'=>2, 'children'=>array( array('id'=>3) ) ) ) ) );
$output = [];
function dejigg($in) {
global $output;
$kids = $in['children'] or array();
unset($in['children']);
$output[] = $in;
foreach ($kids as $child) {
$child['parent'] = $in['id'];
dejigg($child); // recurse
}
}
foreach ($input as $parent)
dejigg($parent);
print_r($output);
And it returns:
Array
(
[0] => Array
(
[id] => 1
)
[1] => Array
(
[id] => 2
[parent] => 1
)
[2] => Array
(
[id] => 3
[parent] => 2
)
)

Categories