PHP Create a Nested Array with indexes from a CSV file - php

I'm having a peculiar issue. I have a CSV file that has Comma Separated Values that I need to upload and then get Nested Array of values based on following 3 conditions;
The array will first loop through all values and get first 4 unique
characters. (Codes)
Match each column values with the with number of
columns in each row and give count of rows that matches 4 digit
codes. (Single_Devices for single column and Dual, Triple and Quad for respective columns count)
Match each column values with code and list all the
columns under the Devices. (Numbers)
CSV file
123429000000000
123429000000001
123429000000010,123429000000011
123429000000040,123429000000041
What I desire is;
Array
(
[Code] => 1234
(
[single_devices] => 2
(
[0] => Array
(
[0] => 123429000000000
)
[1] => Array
(
[0] => 123429000000001
)
)
[dual_devices] => 2
(
[0] => Array
(
[0] => 123429000000010
[1] => 123429000000011
)
[1] => Array
(
[0] => 123429000000040
[1] => 123429000000041
)
)
)
)
Is it possible?
I can manage JSON converted data or object or just associative nested array.
Edit: This is the code I wrote for which was only showing values and not indexes as I desired.
// Get all numbers in array
for ($j = 0; $j < count($csv_file[$i]); $j++){
$numbers[] = $csv_file[$i][$j];
}
// Get codes from numbers
for ($i = 0; $i < count($csv_file); $i++){
for ($j = 0; $j < count($csv_file[$i]); $j++){
$codes[] = substr($csv_file[$i][$j], 0, 4);
}
}
// Get unique codes from codes array
$codes = array_unique($codes);
// Get numbers and sort them codes and device count wise.
for ($i = 0; $i < count($csv_file); $i++){
for ($j = 0; $j < count($csv_file[$i]); $j++){
$q = count($csv_file[$i]); // set device count based on column count
if (count($csv_file[$i]) == $q){ // if device count is equal to column count
foreach ($codes as $code){ // loop through unique codes
if ($code == substr($csv_file[$i][$j], 0, 4)){ // if number's first 4 char matches code
// create array with code and then device count and add numbers
$devices[$code][$q.'_device_numbers'][$i][$j] = preg_replace('/\s+/', '', $csv_file[$i][$j]);
}
}
}
}
}
This is what I am getting from the above code.
Array
(
[1234] => Array
(
[1_sim_imeis] => Array
(
[0] => Array
(
[0] => 123429000000000
)
[1] => Array
(
[0] => 123429000000001
)
)
[2_sim_imeis] => Array
(
[2] => Array
(
[0] => 123429000000010
[1] => 123429000000011
)
[3] => Array
(
[0] => 123429000000040
[1] => 123429000000041
)
)
)
)

This is based on reading the file as a csv (using fgetcsv()) and extracting the first 4 digits of the first value on each line. It then uses another array to give the key for the 'single_devices' etc. key - using the count of the number of elements on the line (-1 as the array is 0 based)...
$fileName = "a.dat";
$output = [];
$baseData = [ 'single_devices', 'dual_devices', 'triple_devices', 'quad_devices' ];
$fh = fopen ( $fileName, "r" );
while ( ($data = fgetcsv($fh)) !== false ) {
$code = substr($data[0], 0, 4);
$output[$code][$baseData[count($data)-1]][] = $data;
}
fclose($fh);
print_r($output);
which with the test data gives...
Array
(
[1234] => Array
(
[single_devices] => Array
(
[0] => Array
(
[0] => 123429000000000
)
[1] => Array
(
[0] => 123429000000001
)
)
[dual_devices] => Array
(
[0] => Array
(
[0] => 123429000000010
[1] => 123429000000011
)
[1] => Array
(
[0] => 123429000000040
[1] => 123429000000041
)
)
)
With
while ( ($data = fgetcsv($fh)) !== false ) {
$code = substr($data[0], 0, 4);
if ( !isset($output[$code])) {
$output[$code] = ["code" => $code];
}
$deviceLabel = $baseData[count($data)-1];
$output[$code][$deviceLabel]['count'] =
($output[$code][$deviceLabel]['count'] ?? 0) + 1;
$output[$code][$deviceLabel][] = $data;
}
you can get an output of...
Array
(
[1234] => Array
(
[code] => 1234
[single_devices] => Array
(
[count] => 2
[0] => Array
(
[0] => 123429000000000
)
[1] => Array
(
[0] => 123429000000001
)
)

Related

Is there a way to remove all repeated keys except the last one in array?

I have array of messages received from server, with key seen_by which contain users saw the message, it's structure :
[1] => Array
(
[seen_by] => Array
(
[1] => user_1
[2] => user_2
[3] => user_3
)
)
[2] => Array
(
[seen_by] => Array
(
[2] => user_2
[3] => user_3
)
)
[3] => Array
(
[seen_by] => Array
(
[3] => user_3
)
)
where they keys in seen_by array is user_id,
what i want to do is since user_2 already in the seen_by array of the second message ,so remove it from the first seen_by array , and since user_3 in seen_by array of third message , remove from the first two messages
I want to get array like
[1] => Array
(
[seen_by] => Array
(
[1] => user_1
)
)
[2] => Array
(
[seen_by] => Array
(
[2] => user_2
)
)
[3] => Array
(
[seen_by] => Array
(
[3] => user_3
)
)
Use foreach loop and loop from last to first. To do so, use array_reverse(). Use a $set to check if a user is already tracked using isset. If it is, unset it from the current subarray or add it to the $set and move with the next element. An array_reverse at the end is done again just to restore the original order.
Snippet:
<?php
function removeDups($data){
$set = [];
$res = [];
foreach(array_reverse($data) as &$sub){
foreach($sub['seen_by'] as $idx => $val){
if(isset($set[ $val ])){
unset($sub['seen_by'][ $idx ]);
}else{
$set[ $val ] = true;
}
}
$res[] = $sub;
}
return array_reverse($res);
}
print_r(removeDups($data));
Online Demo
I've simplified the arrays for illustration but the idea is shown. You can loop through the arrays starting at the end and working backwards, removing elements that exist in later arrays.
$array = array(
array( 1, 2, 3 ),
array( 2, 3 ),
array( 3 ),
);
$len = count( $array );
for ( $i = $len -1 ; $i > 0; $i-- ) {
$curr_array = $array[ $i ];
for( $j = $i - 1; $j >= 0; $j-- ) {
$array[$j] = array_diff( $array[$j], $curr_array );
}
}

How to count more than one items in array_column?

I asked a question called 'How to count items in an array that's in an array?' and now I need help on expanding from that question.
How do you count items in two arrays?
My array looks like this:
Array
(
[0] => Array
(
[acf_fc_layout] => irl_today_website_entry
[irl_today_website] => Array
(
[0] => Array
( data removed)
[1] => Array
( data removed )
)
)
[1] => Array
(
[acf_fc_layout] => irl_today_social_entry
[irl_today_social] => Array
(
[0] => Array
( data remove )
[1] => Array
( data remove)
)
)
)
And I use:
<?php $arrays = get_field('irl_today_entry');
$res = array_map(function($x) {
return count($x);
}, array_column($arrays, 'irl_today_website'));?>
to count items in [irl_today_social]. How do I count items in [irl_today_social] and [irl_today_website]?
I tried array_column($arrays, "irl_today_social", "irl_today_website") and it only counted items in [irl_today_social]
array_map() can be fed multiple arrays to work with. The first array "irl_today_social" elements are referenced by $x, the second "irl_today_website" by $y in this case.
Use following:
$res = array_map(function($x, $y) {
$soc = count($x);
$web = count($y);
return ['soc' => $soc, 'web' => $web];
}, array_column($arrays, "irl_today_social"), array_column($arrays, "irl_today_website"));
array_map() will return an array with the count for each - the result sample output:
Array
(
[0] => Array
(
[soc] => 2
[web] => 3
)
)
demo

How to move a value up to a key, and remove a key. Array manipulation

I'm trying to change my array from this:
Array
(
[0] => Array
(
[BID_OPEN] => Array
(
[0] => 0.718282
)
)
[1] => Array
(
[BID_CLOSE] => Array
(
[0] => 1.654545
)
)
[2] => Array
(
[BID_OPEN] => Array
(
[0] => 1.654878
)
)
)
in to this:
Array
(
[BID_OPEN]
(
[0] => 0.718282
[1] => 1.654878
)
[BID_CLOSE]
(
[0] => 1.654545
[1] => 1.645845
)
)
I'm not sure how to begin. My code:
foreach($array as $keys=>$values)
{
if(!empty($array [$c]['BID_OPEN']))
{
$inital_part1 = array("BID_OPEN", $array [$c]['BID_OPEN']);
}
else
{
echo '';
}
if(!empty($array [$c]['BID_CLOSE']))
{
$inital_part2 = array("BID_CLOSE", $array [$c]['BID_CLOSE']);
}
else
{
echo '';
}
$array1[] = $inital_part1;
$array1[] = $inital_part2;
$c++;
}
I seem to get double outputs, so the foreach when I build arrays is giving me two times the required output. Google reckons it's because I have an array in my array somewhere but I'm precisely sure I don't.
The array came from an object stdclass and I don't know what that is, have googled but haven't found anything useful. Also I'm able to get some figures but only the initial values are correct, the rest of the data doesn't seem to come through. No doubt it's because I used an index[0] to get it working.
After hours any help would be great thanks.
As long as you have told us everything about your input array it can be done quite simply like this
<?php
$in = [ ['BID_OPEN' => [0.718282]],
['BID_CLOSE' => [1.654545]],
['BID_OPEN' => [1.654878]]
];
print_r($in);
$new = []; // new array we are building
foreach ($in as $abid) {
if (array_key_exists('BID_OPEN', $abid) ) {
$new['BID_OPEN'][] = $abid['BID_OPEN'][0];
}
if (array_key_exists('BID_CLOSE', $abid) ) {
$new['BID_CLOSE'][] = $abid['BID_CLOSE'][0];
}
}
print_r($new);
THE INPUT ARRAY: Is like yours
Array
(
[0] => Array
(
[BID_OPEN] => Array
(
[0] => 0.718282
)
)
[1] => Array
(
[BID_CLOSE] => Array
(
[0] => 1.654545
)
)
[2] => Array
(
[BID_OPEN] => Array
(
[0] => 1.654878
)
)
)
RESULT:
Array
(
[BID_OPEN] => Array
(
[0] => 0.718282
[1] => 1.654878
)
[BID_CLOSE] => Array
(
[0] => 1.654545
)
)
$c = 0;
$array1['BID_OPEN'] = [];
$array2['BID_CLOSE'] = [];
foreach($vartttttt as $tunips=>$ert)
{
$d = 0;
foreach($ert as $erts=>$val)
{
//$array[] = $erts;
if($erts == 'BID_OPEN')
{
array_push($array1['BID_OPEN'], $val[0]);
}
if($erts == 'BID_CLOSE')
{
array_push($array2['BID_CLOSE'], $val[0]);
}
$d++;
}
$c++;
}
$array = array_merge($array1, $array2);

PHP - get array element between a range in multidimensional array

I have a multidimensional array. I want to get array element which value is greater than 2 and less than 17. My Array is given below:
Array
(
[4] => Array
(
[0] => 17
[1] => 15
[2] => 12
)
[5] => Array
(
[0] => 16
)
[2] => Array
(
[0] => 3
[1] => 1
)
[1] => Array
(
[0] => 2
)
)
I want output like below:
Array
(
[4] => Array
(
[0] => 17
[1] => 15
[2] => 12
)
[5] => Array
(
[0] => 16
)
[2] => Array
(
[0] => 3
[1] => 1
)
)
Please help me how can I do it easy & fast method.
You can use a nested array filter.
$result = array_filter($outer_array, function($inner_array) {
return array_filter($inner_array, function($number) {
return $number > 2 && $number < 17;
});
});
Then inner array filter will result in an empty array being passed to the outer array filter if no values are found in the specified range. The empty array will evaluate to false in the outer filter callback, eliminating that array from the result.
Demo at 3v4l.org.
Generally, we want you to show what you have tried before we'll write code for you, but this one's on the house. For future reference, include some code snippets along with your question to avoid getting downvoted.
$output = array();
for($i = 0; $i < count($arr); $i++)
{
$use = false;
for($j = 0; $j < count($arr[$i]); $j++)
{
if($arr[$i][$j] > 2 and $arr[$i][$j] < 17)
{
$use = true;
break;
}
}
if($use)
$output[] = $arr[$i];
}
return $output;

How to remove same values from two arrays?

I have tried array_merge and array_unique but it couldn't helped me out.
Here is my code:
public function syncContacts() {
$data['data'] = $this->main_manager->select_all('users'); # get all user data
$info[0] = [
"contact_name" => "a",
"number" => "031651651"
];
$info[1] = [
"contact_name" => "b",
"number" => "+923402382972"
];
$info[2] = [
"contact_name" => "c",
"number" => "31651651"
];
$info[3] = [
"contact_name" => "d",
"number" => "6165165123323"
];
$info[4] = [
"contact_name" => "e",
"number" => "316516512113"
];
for ($i = 0; $i < count($info); $i++) { # info array loop
if (substr($info[$i]['number'], 0, 1) == "+") { # finds + sign in numbers
for ($x = 0; $x < count($data['data']); $x++) { # user data array loop
if (
$info[$i]['number'] == $data['data'][$x]['country_code'] . $data['data'][$x]['phone_number'] # first condition
|| $info[$i]['number'] == $data['data'][$x]['country_code'] . 0 . $data['data'][$x]['phone_number'] # second condition
) {
$finalData['data']['registered'][$i]['name'] = $info[$i]['contact_name'];
$finalData['data']['registered'][$i]['number'] = $info[$i]['number'];
} else {
$finalData['data']['unregistered'][$i]['name'] = $info[$i]['contact_name'];
$finalData['data']['unregistered'][$i]['number'] = $info[$i]['number'];
$result = array_unique(array_merge($finalData['data']['unregistered'][$i], $info[$i]));
//
}
} # end of user data array loop
} else { # finds 0 in numbers
for ($x = 0; $x < count($data['data']); $x++) { # user data array loop
if (
$info[$i]['number'] == $data['data'][$x]['phone_number'] # first condition
|| 0 . $info[$i]['number'] == $data['data'][$x]['phone_number'] # second condition
|| $info[$i]['number'] == 0 . $data['data'][$x]['phone_number'] # third condition
) {
$finalData['data']['registered'][$i]['name'] = $info[$i]['contact_name'];
$finalData['data']['registered'][$i]['number'] = $info[$i]['number'];
} else {
$finalData['data']['unregistered'][$i]['name'] = $info[$i]['contact_name'];
$finalData['data']['unregistered'][$i]['number'] = $info[$i]['number'];
$result = array_unique(array_merge($finalData['data']['unregistered'][$i], $info[$i]));
// $result = array_merge($finalData['data']['unregistered'][$i], $info[$i]);
// $finalData['data']['unregistered'][$i] = array_unique($result);
}
} # end of user data array loop
}
} #end of info array loop
print_r($finalData);
die();
}
I am making a sync contacts webservice.
In $data array I am getting data from users table and I have 8 record in it.
3 record matched from my given array which is $info and two are unmatched. I made an array which is $finalData['data'].
I have to separate the record in registered and unregistered key of $finalData array. I have separated matched numbers in registered key of an array but couldn't separate the correct unmatched numbers in unregistered key of the array.
I am getting this result:
Array
(
[data] => Array
(
[unregistered] => Array
(
[0] => Array
(
[name] => a
[number] => 031651651
)
[1] => Array
(
[name] => b
[number] => +923402382972
)
[2] => Array
(
[name] => c
[number] => 31651651
)
[3] => Array
(
[name] => d
[number] => 6165165123323
)
[4] => Array
(
[name] => e
[number] => 316516512113
)
)
[registered] => Array
(
[0] => Array
(
[name] => a
[number] => 031651651
)
[1] => Array
(
[name] => b
[number] => +923402382972
)
[2] => Array
(
[name] => c
[number] => 31651651
)
)
)
)
Match index of first array with another and unset the matched index and then you will get the unregistered numbers.
How about using a hash like array? See example here http://php.net/manual/en/language.types.array.php

Categories