PHP, Building ID'd array from non-incremental ID'd CSV - php

Basically, here is my CSV File:
1,"Gold"
2,"English Version"
10,"Sword+0"
11,"Sword+1"
12,"Sword+2"
And so on, you get the idea. There are other parts where the ID is not incremental, perhaps one is 2899 and then the next one is 3020. I'm trying to build an array from this with fgetcsv();. I can do it fine, but I've failed so far to match up my array IDs with the ID from the CSV.
Here's a simple one that simply builds an incremental array from the file:
$file = fopen("item_proto.csv", "r");
$i = 1;
while(! feof($file)){
$gvar['item'][$i] = (fgetcsv($file));
$i++;
}
fclose($file);
This of course results in:
Array
(
[item] => Array
(
[1] => Array
(
[0] => 1
[1] => Gold
)
[2] => Array
(
[0] => 2
[1] => English Version
)
[3] => Array
(
[0] => 10
[1] => Sword+0
But I'd like [item][x] to match up with [item][x][y].

Try this:
$file = fopen("item_proto.csv", "r");
$i = 1;
while(! feof($file)){
$line = fgetcsv($file);
$gvar['item'][$line[0]] = $line;
$i++;
}
fclose($file);

Related

How to separate csv array by column?

I have a giant list in excel, they are just two columns
name type
The file is currently being read:
$lines = array_map('str_getcsv', file('file.csv', FILE_IGNORE_NEW_LINES));
print_r($lines); returns:
name1;type
name2;type2
...
Array ( [0] => Array ( [0] => name1;type1) [1] => Array ( [0] => name2;type2)...
I would like to access separate name and type in an foreach
How can I do this?
Thanks
str_getcsv default delimiter is ',' so you need call it somehow with explicitly specifying ';' as delimeter
for example like this
$myGetCsv = function ($str) {
return str_getcsv($str, ';');
};
$lines = array_map($myGetCsv, file('file.csv', FILE_IGNORE_NEW_LINES));
Use this code for CSV file reading. it ease to use and understand how its work.
if (($handle = fopen('./suppression_invalid_emails.csv', "r")) !== false) {
//getting column name
$column_headers = fgetcsv($handle);
foreach ($column_headers as $header) {
//column as array;
$result[$header] = array();
}
// get data for column;
while (($data = fgetcsv($handle)) !== false) {
$i = 0;
foreach ($result as &$column) {
$column[] = $data[$i++];
}
}
fclose($handle);
echo '<pre>'; print_r($result); echo '</pre>';
}
i use two basic function for this 1st one is fopen for reading file and other is fgetcsv for getting data for column.
and result is:
Array
(
[reason] => Array
(
[0] => Mail domain mentioned in email address is unknown
[1] => Known bad domain
[2] => Known bad domain
)
[email] => Array
(
[0] => muneque#collegeclub.om
[1] => saharfa2000#hatmail.com
[2] => tawheeda81#yahoo.co
)
[created] => Array
(
[0] => 1502644294
[1] => 1502480171
[2] => 1502344320
)
)

Convert CSV into Array

I have a csv file that looks like this:
Did,status
"123","Active"
"456","Not-Active"
"789","Active"
....and so on
I would like to be able to convert it into an array that looks like this:
$DidStatus = array("123"=>"Active", "456"=>"Not-Active", "789"=>"Active");
I tried this but it's not what I'm looking for:
$file = file_get_contents("test.csv");
$data = array_map("str_getcsv", preg_split('/\r*\n+|\r+/', $file));
print_r($data);
but the output is not the one I'm looking for:
Array
(
[0] => Array
(
[0] => Did
[1] => status
)
[1] => Array
(
[0] => 123
[1] => Active
)
[2] => Array
(
[0] => 456
[1] => Not-Active
)
[3] => Array
(
[0] => 789
[1] => Active
)
[4] => Array
(
[0] =>
)
)
Look into fgetcsv()
<?php
$handle = fopen("test.csv", "r");
$result = Array();
fgetcsv($handle); //Removes the first line of headings in the csv
while($data = fgetcsv($handle)) {
$result[$data[0]] = $data[1];
}
print_r($result); //the result
?>
There are other ways to do it, but given your current code, just extract an array of the 1 values and index it by the 0 values.
unset($data[0]); //If needed to remove the header row
$data = array_column($data, 1, 0);
You may consider this as an alternate for the first step (not sure if FILE_IGNORE_NEW_LINES is absolutely necessary):
$data = array_map('str_getcsv', file('test.csv', FILE_IGNORE_NEW_LINES));
Look into fgetcsv. That is meant to be used for something like this.
$arr = array();
$file = fopen('test.csv', 'r');
while (($result = fgetcsv($file)) !== FALSE)
{
$arr[] = $result;
}
fclose($file);
You can use this package league/csv and you can find instructions on how to use it here - one of the first examples shows how to convert csv to array

How to break an array and use part of it with PHP

I am new to this so your help is much needed. I have a CSV file and I need to modify the last column of this CSV. What I did is separated the columns in array using this code below.
<?php
function readCSV($csvFile){
$file_handle = fopen($csvFile,"r");
while (!feof($file_handle)) {
$line_of_text[] = fgetcsv($file_handle, 1024);
}
fclose($file_handle);
return $line_of_text;
}
$csvFile = 'testslash.csv';
$csv = readCSV($csvFile);
print_r($csv);
?>
This is the output i am getting which is fine .. what i want to end up with ex: array 0,2 and array 1,2. i tried array slice but with no avail. any other options?
Array
(
[0] => Array
(
[0] => ABC
[1] => XXX
[2] => 972 54 120000 / 129999
)
[1] => Array
(
[0] => DEF
[1] => XXX
[2] => 972 52 1100180 / 9
)
)
You're saying you want only a specific part of the subarrays.
This is easily done using a foreach loop and a new array.
$resultArray = array();
foreach($cvs as $row)
{
$resultArray[] = $row[2]; //if you dont care about the index of the array
$resultArray[$row[0]] = $row[2]; //if you want to speficy the index as the value of e.g. the first entry of the subarray;
}

PHP - Fastest way to convert a 2d array into a 3d array that is grouped by a specific value

I would like to convert this two dimensional array of records:
[records] => Array
(
[0] => Array
(
[0] => Pears
[1] => Green
[2] => Box
[3] => 20
)
[1] => Array
(
[0] => Pears
[1] => Yellow
[2] => Packet
[3] => 4
)
[2] => Array
(
[0] => Peaches
[1] => Orange
[2] => Packet
[3] => 4
)
[3] => Array
(
[0] => Apples
[1] => Red
[2] => Box
[3] => 20
)
)
Into this three dimensional array where each array key is grouped by a certain value from the original array:
[converted_records] => Array
(
[Pears] => Array
(
[0] => Array
(
[0] => Green
[1] => Box
[2] => 20
)
[1] => Array
(
[0] => Yellow
[1] => Packet
[2] => 4
)
)
[Peaches] => Array
(
[0] => Array
(
[0] => Orange
[1] => Packet
[2] => 4
)
)
[Apples] => Array
(
[0] => Array
(
[0] => Red
[1] => Box
[2] => 20
)
)
)
I can do this like so:
$array = // Sample data like the first array above
$storage = array();
$cnt = 0;
foreach ($array as $key=>$values) {
$storage[$values[0]][$cnt] = array (
0 => $values[1],
1 => $values[2],
2 => $values[3]
);
$cnt ++;
}
I wanted to know if there is a more optimal way to do this. I am not aware of any functions within PHP that are capable of this so I can only assume that this is basically how it would be done.
The problem is though, this is going to be repeated so so many times and every little millisecond is going to count so I really want to know what is the best way to accomplish this task?
EDIT
The records array is created by parsing a .CSV file as follows:
$records = array_map('str_getcsv', file('file.csv'));
EDIT #2
I did a simple benchmark test on a set of 10 results (5k records each) to get an average runtime of 0.645478 seconds. Granted there is a few other things going on before this so this is not a true indication of actual performance but a good indication for comparison to other methods.
EDIT #3
I did a test with about 20x the records. The average of my routine was 14.91971.
At some point the answer below by #num8er had $records[$key][] = array_shift($data); before updating the answer as it is now.
When I tried testing with the larger set of results this it ran out of memory as its generating an error for each record.
This being said, once i did $records[$key][] = $data; the routine completed with an average of 18.03699 seconds with gc_collect_cycles() commented out.
I've reached the conclusion that although #num8ers method is faster for smaller files, for larger ones my method works out quicker.
If you're only looking for some clean code:
$array = array_map('str_getcsv', file('file.csv'));
$storage = array();
foreach ($array as $values) {
$key = array_shift($values);
$storage[$key][] = $values;
}
Unless you have hundreds of thousands of array entries, speed shouldnt be a concern either.
reading big file to memory using file() (1st iteration when it reads file)
and then iterating lines using array_map (2nd iteration after each line of file is read to array)
doing foreach on array (3rd iteration)
it is bad idea when You're looking for performance.
You're iterating 3 times. so what about 100K records? it will iterate 300K times?
most performant way is to do it while reading file. there is only 1 iteration - reading lines (100K records == 100K iteration):
ini_set('memory_limit', '1024M');
set_time_limit(0);
$file = 'file.csv';
$file = fopen($file, 'r');
$records = array();
while($data = fgetcsv($file)) {
$key = $data[0];
if(!isset($records[$key])) {
$records[$key] = array();
}
$records[$key][] = array(0 => $data[1],
1 => $data[2],
2 => $data[3]);
gc_collect_cycles();
}
fclose($file);
and here is parent -> children processing for huge files:
<?php
ini_set('memory_limit', '1024M');
set_time_limit(0);
function child_main($file)
{
$my_pid = getmypid();
print "Starting child pid: $my_pid\n";
/**
* OUR ROUTINE
*/
$file = fopen($file, 'r');
$records = array();
while($data = fgetcsv($file)) {
$key = $data[0];
if(!isset($records[$key])) {
$records[$key] = array();
}
$records[$key][] = array(0 => $data[1],
1 => $data[2],
2 => $data[3]);
gc_collect_cycles();
}
fclose($file);
unlink($file);
return 1;
}
$file = __DIR__."/file.csv";
$files = glob(__DIR__.'/part_*');
if(sizeof($files)==0) {
exec('split -l 1000 '.$file.' part_');
$files = glob(__DIR__.'/part_*');
}
$children = array();
foreach($files AS $file) {
if(($pid = pcntl_fork()) == 0) {
exit(child_main($file));
}
else {
$children[] = $pid;
}
}
foreach($children as $pid) {
$pid = pcntl_wait($status);
if(pcntl_wifexited($status)) {
$code = pcntl_wexitstatus($status);
print "pid $pid returned exit code: $code\n";
}
else {
print "$pid was unnaturally terminated\n";
}
}
?>

Reading 2D Array from a text file, HELP!

UPDATE: I realized that the issue was I was using print instead of echo to print the data, so it was showing the array instead of the data within it. Thanks a ton guys!
I currently have a text file that looks like this:
0,0,0,0,0
0,0,0,0,0
0,0,0,0,0
0,0,0,0,0
0,0,0,0,0
And I'm using this function:
function rFile($fileName){
$resultF = fopen($fileName, "r") or die("can't open file");
$array = array(); //Create the first dimension of a 2D array
$i=0;
while(!feof($resultF)){
$line = fgets($resultF);
$line = trim($line, "\n");
$tokens = explode(",",$line);
$array[$i]=array(); //Create the second dimension of the 2D array
$tokenCount = sizeof($tokens);
for($j=0; $j<$tokenCount; $j++){
$array[$i][$j] = $tokens[$j];
}
$i++;
}
return $array;
}
Essentially, it's supposed to read through the file, explode each "0" and store it in a 2D array, $array. For some reason it returns this:
Array[0]
Array[1]
Array[2]
....etc etc
Anyone know what I did wrong?
PHP multi-dimensional arrays are just arrays of arrays. There's no need for the inner loop. You can just do
while(...) {
... fgets stuff
$array[$i] = explode(',', $line);
$i++;
}
and get the same effect.
You're going about it the hard way, by using for loops and counters. By using PHP's $array[] = $val append syntax, you can save a lot of effort here.
// all the file handling code...
while(!feof($resultF)){
$line = fgets($resultF);
$line = trim($line, "\n");
$tokens = explode(",",$line);
// Append the line array.
$array[] = $tokens; //Create the second dimension of the 2D array
}
return $array;
Or to be even more concise:
$array[] = explode(",",$line);
try this :
function rFile($filename) {
$lines = file($filename);
if ($lines !== false) {
foreach ($lines as & $line) {
$line = explode(',', trim($line, '\n\r'));
}
}
return $lines;
}
$f = file($fileName);
$results = array();
foreach ($f as $line) {
$line = preg_replace("\n", "", $line);
$results[] = explode(",", $line);
}
Hmm, since this is comma delimitated, we can use fgetcsv to make this short and simple:
$file = fopen('test.txt', 'r');
$matrix = array();
while($entries = fgetcsv($file)) {
$matrix[] = $entries;
}
fclose($file);
Resulting array:
Array
(
[0] => Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0
[4] => 0
)
[1] => Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0
[4] => 0
)
[2] => Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0
[4] => 0
)
[3] => Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0
[4] => 0
)
[4] => Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0
[4] => 0
)
)

Categories