CSV to Associative Array

CSV to Associative Array

run over the csv file line by line, and insert to array like:

$array = $fields = array(); $i = 0;
$handle = @fopen("file.csv", "r");
if ($handle) {
while (($row = fgetcsv($handle, 4096)) !== false) {
if (empty($fields)) {
$fields = $row;
continue;
}
foreach ($row as $k=>$value) {
$array[$i][$fields[$k]] = $value;
}
$i++;
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}

PHP CSV to associative array with top row as keys and following rows as values

this is wrong:

// original string
$OriginalString = "fname,lname,a,b,c,d,e,f"

your original string had newlines which are very important here, meaning your $OriginalString should be:

// original string
// original string
$OriginalString = "fname,lname
a,b
c,d
e,f";

from there you can explode the string by lines,

$lines = explode("\n",$originalString);

from there it gets kindof-complex, you can iterate the lines with foreach, keeping in mind that the first line gives you the keys, and once you parse out the keys, you can iterate the next lines fragments with another explode+foreach, like

$keys = array();
$parsed = array();
foreach($lines as $lineno => $line){
if($lineno === 0){
// the first line is special, it contains the keys
$keys = explode(",",$line);
continue;
}
$fragments = explode(",", $line);
$current=array();
foreach($fragments as $fragment_number => $value){
$current[ $keys[$fragment_number] ]=$value;
}
$parsed [] = $current;
}

which gives

[
{
"fname": "a",
"lname": "b"
},
{
"fname": "c",
"lname": "d"
},
{
"fname": "e",
"lname": "f"
}
]

PHP: Write values of associative array in a column of CSV file based on their keys

You can do this with a loop saving all your table keys. Then you check all the keys on each line, if the key is missing, create it with an empty string !

$fp = fopen('file.csv', 'wb');
$savedKeys = [] ;
foreach ($csv as $getKey) {
$savedKeys = array_merge($savedKeys,array_keys($getKey)) ;
}

$savedKeys =array_unique($savedKeys) ;

foreach ($csv as $fields) {

foreach ($savedKeys AS $checkKey){
if (!isset($field[$checkKey])){
$field[$checkKey] = '';
}
}
fputcsv($fp, $fields);
}

fclose($fp);

Convert csv rows to associative array

The usual way to do this is with array_combine

$file = file_get_contents($url);    // Read file into array
$rows = explode("\n", $file); // Separate lines
$headings = explode(',', $rows[0]); // Turn headings on first line into array
unset($rows[0]); // Remove headings from data set
$data = [];
foreach ($rows AS $row)
$data[] = array_combine($headings, explode(',', $row));

Result:

array(3) {
[0]=>
array(3) {
["Date"]=>
string(9) "17-Nov-17"
["Value1"]=>
string(2) "34"
["Value2"]=>
string(2) "42"
}
[1]=>
array(3) {
["Date"]=>
string(9) "16-Nov-17"
["Value1"]=>
string(2) "22"
["Value2"]=>
string(2) "35"
}
[2]=>
array(3) {
["Date"]=>
string(9) "15-Nov-17"
["Value1"]=>
string(2) "19"
["Value2"]=>
string(2) "24"
}
}

How do I convert CSV data into an associative array using Bash 4?

The following script:

csv_to_array() {
local -a values
local -a headers
local counter

IFS=, read -r -a headers
declare -a new_array=()
counter=1
while IFS=, read -r -a values; do
new_array+=( row$counter )
declare -A "row$counter=($(
paste -d '' <(
printf "[%s]=\n" "${headers[@]}"
) <(
printf "%q\n" "${values[@]}"
)
))"
(( counter++ ))
done
declare -p new_array ${!row*}
}

foo2() {
source <(cat)
declare -p new_array ${!row*} |
sed 's/^/foo2: /'
}

echo "==> TEST 1 <=="

cat <<EOF |
id,title,url,description
1,foo name,foo.io,a cool foo site
2,bar title,http://bar.io,a great bar site
3,baz heading,https://baz.io,some description
EOF
csv_to_array |
foo2

echo "==> TEST 2 <=="

cat <<EOF |
name,age,gender
bob,21,m
jane,32,f
EOF
csv_to_array |
foo2

will output:

==> TEST 1 <==
foo2: declare -a new_array=([0]="row1" [1]="row2" [2]="row3")
foo2: declare -A row1=([url]="foo.io" [description]="a cool foo site" [id]="1" [title]="foo name" )
foo2: declare -A row2=([url]="http://bar.io" [description]="a great bar site" [id]="2" [title]="bar title" )
foo2: declare -A row3=([url]="https://baz.io" [description]="some description" [id]="3" [title]="baz heading" )
==> TEST 2 <==
foo2: declare -a new_array=([0]="row1" [1]="row2")
foo2: declare -A row1=([gender]="m" [name]="bob" [age]="21" )
foo2: declare -A row2=([gender]="f" [name]="jane" [age]="32" )

The output comes from foo2 function.

The csv_to_array function first reads the headaers. Then for each read line it adds new element into new_array array and also creates a new associative array with the name row$index with elements created from joining the headers names with values read from the line. On the end the output from declare -p is outputted from the function.

The foo2 function sources the standard input, so the arrays come into scope for it. It outputs then those values again, prepending each line with foo2:.

CSV to Associative Array (One column as key and another as value)

With array_map you can parse the csv data and have an array to do as you wish.
Example:

// Parsing the data in csv file
$csv = array_map('str_getcsv', file('path/file.csv'));

/*At this point you already have an array with the data but
* the first row is the header row in your csv file */

//remove header row
array_shift($csv);

$data = [];

//Walk the array and add the needed data into some another array
array_walk($csv, function($row) use (&$data) {
$data[$row[3]] = $row[8];
});

And that's it.

However the data you show as an example has duplicate UPCs. You will overwrite some data if you want an array with the structure 'UPC' => 'Qty' . You can't have duplicate keys in an array.

If what you are looking for is to get the total Qty for each UPCs then you just need to add the already existing Qty with the new one if the UPC key already exists.

// Parsing the data in csv file
$csv = array_map('str_getcsv', file('file.csv'));

//remove header row
array_shift($csv);

$data = [];

//Walk the array and add the needed data into another array
array_walk($csv, function($row) use (&$data) {

$data[$row[3]] = ($data[$row[3]] ? $data[$row[3]] + (int) $row[8] : (int) $row[8]);
});

Or longer but clearer.

//Walk the array and add the needed data into another array
array_walk($csv, function($row) use (&$data) {

if(!empty($data[$row[3]]))
{
$data[$row[3]] += (int) $row[8];
}
else {
$data[$row[3]] = (int) $row[8];
}
});

PHP CSV to Associative Array with Row Headings

You need a second foreach to achieve what you want.

Something like this:

foreach ($all_rows as $row) {
if($row) {
foreach($row as $key => $val) {
if($key == "Food" && $val == "Apples") {
echo "Apples: " . "<br>";
echo $row["In_Stock"] . "<br>";
echo $row["On_order"] . "<br>";
}
else if($key == "Food" && $val == "Oranges") {
echo "Oranges: " . "<br>";
echo $row["In_Stock"] . "<br>";
echo $row["On_order"] . "<br>";
}
}
}
}

If you just want to print the values on your page, this could do it.

But I since you've mentioned to just call the values based on food type, you can create a function out of this.

PHP CSV to associative array with top row as keys and columns as value arrays

Instead of building the end array as you go along. This code reads the header row before the loop, then just reads all of the data lines into another array. It then combines each element of the header array with the matching column from the data array (using array_column() and the position of the header element)...

function readCSV($csvFile) {
$aryData = [];
$output = [];
$header = NULL;
$handle = fopen($csvFile, "r");
if($handle){
$header = fgetcsv($handle);
while ($aryData[] = fgetcsv($handle));
foreach ( $header as $key=>$label) {
$output[$label] = array_column($aryData, $key);
}
fclose($handle);
}
return $output;
}

Reading CSV in Bash into a Dictionary/Associative array

Here's why you don't get the output you expect:

    Bellum:scripts rocky$ od -c foobar.csv
0000000 357 273 277 f o o - 1 , b a r - 1 \r \n
0000020 f o o - 2 , b a r - 2 \r \n f o o
0000040 - 3 , b a r - 3
0000050
  1. the name on first line does not contain just "foo-1" -- there are extra characters in there.
    • They can be removed with "${name#$'\357\273\277'}"
  2. the last line does not end with a newline, so the while-read loop only iterates twice.
    • read returns non-zero if it can't read a whole line, even if it reads some characters.
    • since read returns "false", the while loop ends.
    • this can be worked around by using:
      while IFS=, read -r name title || [[ -n $title ]]; do ... 
      #............................. ^^^^^^^^^^^^^^^^^^
    • or, just fix the file.

Result:

BOM=$'\357\273\277'
CR=$'\r'

declare -A descriptions
while IFS=, read name title || [[ $title ]]; do
descriptions["${name#$BOM}"]=${title%$CR}
done < foobar.csv

declare -p descriptions
echo "${descriptions["foo-1"]}"
echo "${descriptions["foo-2"]}"
echo "${descriptions["foo-3"]}"
declare -A descriptions=([foo-1]="bar-1" [foo-2]="bar-2" [foo-3]="bar-3" )
bar-1
bar-2
bar-3


Related Topics



Leave a reply



Submit