How to put associative array in csv using PHP? - php

Hello guys just want to ask how can I put an associative array in csv?
For example if I have an array like this.
Array
(
[0] => Array
(
[restaurant_id] => 1227
[new_lat] => 13.62241
[new_long] => 123.19341
[date_updated] => 2013-11-14 11:20:26
)
[1] => Array
(
[restaurant_id] => 1218
[new_lat] => 14.66732
[new_long] => 121.02618
[date_updated] => 2013-11-14 11:22:22
)
)
For my code in generating csv is this:
$restaurant_id = $post_data['company_id'];
$new_lat_entry = $post_data['new_lat'];
$new_long_entry = $post_data['new_long'];
$data_add = array(
'restaurant_id' => $restaurant_id,
'new_lat' => $new_lat_entry,
'new_long' => $new_long_entry,
'date_updated' => date('Y-m-d H:i:s')
);
$data = unserialize(file_get_contents('addresses.txt'));
$data[] = $data_add;
$serialize_data = serialize($data);
file_put_contents("addresses.txt", $serialize_data, LOCK_EX); //write the text file
$array = unserialize(file_get_contents('addresses.txt')); //THIS WILL GET THE ARRAY
echo "<pre>";
print_r($array); //display it
$csv = '';
foreach($array as $row) {
$csv .= implode(',', $row) . "\n";
}
//fn_print_die($csv);
$file_input = fopen("addresses.csv","w");
foreach($csv as $line){
fputcsv($file_input,split(',',$line));
}
fclose($file_input);

This should work...
<?php
foreach ($array as $row) {
fputcsv($file_input, $row);
}
fclose($file_input);
?>
Just refer to the fputcsv manual on php.net

You should try to implement SPL classes when possible:
$csv_file = new SplFileObject('addresses.csv', 'w');
foreach ($address_list as $address_fields) {
$csv_file->fputcsv($address_fields);
}

You can use implode to do something like this pretty easily
$csv = '';
foreach($array as $row) {
$csv .= implode(',', $row) . "\n";
}

To make this clean, you would have to
collect all keys from the array (foreach twice)
build a second array with each restaurant (no subnodes)
merge the keys array into that and THEN
merge all restaurant subnodes to those keys.
The reason is simple: restaurant A has "[self_service] => true"
The CSV line for restaurant B will either miss a column or worse, have "[vegetarian_food] => false" instead.
In the end, you would have "true" and "false" in the same column under each other, with theo first meaning "Yes, self service" and the second meaning "Sorry veggies". You will probably never notice, because they might still have the same count(array).
(I would write this as a comment, but my Stack Exchange reputation does not allow me that yet (48 now, 2 more to go, yay!)

Related

How to add $_POST values in a multi-dimensional array (PHP)?

I know there may be sources for this out there but I'v tried everything and I'm still not getting the proper solution. That why I'm asking for you help out here.
I have a $_POST array and I want to put values in a an array. Here is the final out I want:
$response = [
['category' => 2, 'value' => "june"],
['category' => 5, 'value' => "may"],
['category' => 8, 'value' => "april"]
]
Here is the catch,the $_POST contains a value of an integer with a space in between and then a string eg '2 june', '5 may' etc
When I get this value, I split it using explode then I try to add the individual values into the response array. This is only adding just one result.
What I tried:
$response = [];
foreach ($_POST as $key => $value) {
$split = explode(" ", $value);
$result = ['category' => $split[0], 'value' => $split[1]];
$response[] = $result;
}
for some reason, the results are not as suggested above. Any ideas and suggestion will be appreciated.
Basically, problem is in the $_POST. This is global array with submitted key-values data. You should NOT use
foreach ($_POST as $key => $value) {
for parsing your data without any checks. This data is submitted by user, and not always they will have format you're waiting for.
For example, if you have a variable "dates" in your HTML form, you should be ready that $_POST['dates'] will be an array of all of your '5 june', '7 july', etc. Don't forget to check and validate all user data you received. It's important by security reason too.
Your code (foreach body, without condition) is ok, I've checked it. Try to set print_r() before explode() you will see that your're working with an array, not with a string.
Your question doesn't have an issue with processing the data into the correct resulting array. The onus falls on $_POST not holding the expected data.
All answers to this question are powerless to fix your $_POST data because no html form was supplied with your question. The only potential value that can be offered is to refine your array building process.
Here are two methods that improve your process by reducing the number of declared variables:
Demonstration uses $a=array('2 june','5 may','8 april'); to represent your $_POST array.
One-liner in a foreach loop:
foreach($a as $v){
$r[]=array_combine(["category","value"],explode(" ",$v));
}
One-liner with no loop:
$r=array_map(function($v){return array_combine(["category","value"],explode(" ",$v));},$a);
Using either process the resulting $r will be:
array (
0 =>
array (
'category' => '2',
'value' => 'june',
),
1 =>
array (
'category' => '5',
'value' => 'may',
),
2 =>
array (
'category' => '8',
'value' => 'april',
),
)
References for used functions:
explode() , array_combine() , array_map()
Try this one:
$response = [];
// just for example use this one
$data = "2 june, 5 may, 7 july";
$temp = explode(",", $data);
// and you can use this one for your case
/*$data = $_POST['var_name']; // var_name is your variable name from $_POST
$temp = explode(",", $data);*/
foreach ($temp as $key => $value) {
$split = explode(" ", trim($value));
foreach ($split as $val) {
$result = ['category' => $split[0], 'value' => $split[1]];
}
$respon[] = $result;
}
echo "<pre>";
echo print_r($respon);
echo "</pre";
the output:
Array
(
[0] => Array
(
[category] => 2
[value] => june
)
[1] => Array
(
[category] => 5
[value] => may
)
[2] => Array
(
[category] => 7
[value] => july
)
)
$response = array();
foreach ($_POST as $key => $value) {
$split = '';
$split = explode(" ", $value);
$result = array('category' => $split[0], 'value' => $split[1]);
$response[] = $result;
}

How to select and print only the value of a nested array?

I'm trying to create an array only from the basename of the url's of $member1 and $member2 and so on to $member(n).
the base array i'm using looks like this for a reason, since I'm using it for another foreach loop.
So the scheme looks like this:
$member1 = 'http://www.bla-bla.com/aFolder/anotherFolder';
$member2 = 'http://www.yada-yada.com/yetAnotherFolder/innerFolder';
$member3 = 'http://www.boo-boo.com/abcs/folder';
//this is the main array
$teams = array(
array("url" => $member1, "selector" => "a"),
array("url" => $member2, "selector" => "input"),
array("url" => $member3, "selector" => "h1"),...,...);
I would like to build a foreach that would create at the end an array with the values with basename($member(n)).
I would like my result to look like this:
Array
(
[0] => anotherFolder
[1] => innerFolder
[2] => folder
)
Thus far I've tried different ways to extract that specific value with no avail, I couldn't find a way on how to extract that specific value.
I'll appreciate the help.
$basenames = [];
foreach ($teams as $team) {
$basenames[] = basename($team['url']);
}
function getBaseName($array){
$return=array();
foreach($array as $arr)
{
$exp=explode("/",$arr['url']);
$return[]=array_pop($exp);
}
return $return;
}
$basenames[]=getBaseName($teams);
If I understood you right, try this:
$resArray = array();
foreach($teams as $team){
$resArray[] = basename($team['url']);
}
The solution using array_map and basename functions:
...
$result = array_map(function($v){ return basename($v['url']); }, $teams);
$array = array();
foreach($teams as $team){
$array[] = basename($team["url"]);
}
print_r($array);
will print
Array
(
[0] => anotherFolder
[1] => innerFolder
[2] => folder
)

what should i do to get array like this in php?

I have one array as below :
Array
(
[Sep] => Array
(
[Support Help Desk] => 24.67
[Development] => 7.74
[Consulting Services] => 4.04
)
[Oct] => Array
(
[Support Help Desk] => 14.38
[Business Activity] => 1.92
[Maintenance Tasks] => 1.00
[Development] => 2.11
)
)
and i want array like this :
Array
(
[Support Help Desk] => 24.67,14.38
[Development] => 7.74,2.11
[Consulting Services] => 4.04,0
[Business Activity] => 0,1.92
[Maintenance Tasks] => 0,1.00
)
I am using php with zend framework.
But i don't know what method should i use to get array like this ?
can anyone please guide me ?
-
Thanks in advance.
Third time lucky! I missed out on some subtleties in the question originally. Try the following code - it's a bit loopy but it should work for you.
I am assuming that your original array is called $data.
// first we need to 'normalise' or fill in the blanks in the contents of the sub array
// get a unique list of all the keys shared - doing it manually here
$keys = ['Support Help Desk', 'Business Activity', 'Maintenance Tasks', 'Development', 'Consulting Services'];
// create a default array with $keys, assigning 0 as the value of each
$default = array_fill_keys($keys, 0);
// next fill in the blanks...
// get the diff (missing keys) between the current element and the default array
// merge the missing key/value pairs
array_walk($data, function(&$month, $key, $default) {
$diff = array_diff_key($default, $month);
$month = array_merge($diff, $month);
}, $default);
// now the array is normalised
// flatten the array... where there are duplicate values for a key, and
// there will be in all cases now including default values
// a sub array is created
$merged = call_user_func_array('array_merge_recursive', $data);
// finally loop over the merged array
// and implode each array of values into a comma separated list
foreach ($merged as &$element) {
if (is_array($element)) {
$element = implode(', ', $element);
}
}
// done :)
var_dump($merged);
Yields:
array (size=5)
'Business Activity' => string '0, 1.92' (length=7)
'Maintenance Tasks' => string '0, 1' (length=4)
'Support Help Desk' => string '24.67, 14.38' (length=12)
'Development' => string '7.74, 2.11' (length=10)
'Consulting Services' => &string '4.04, 0' (length=7)
Hope this helps :)
EDIT
Live example at eval.in
Let's say your array is stored in $main_arr and result array is $result_arr.
$result_arr = array();
foreach ($main_arr as $month) {
foreach ($month as $key => $val) {
if (!isset($result_arr[$key])) {
$result_arr[$key] = array($val);
} else {
array_push($result_arr[$key], $val);
}
}
}
foreach ($result_arr as $key => $val) {
$result_arr[$key] = implode(', ', $val);
}
print_r($result_arr); //Final output.

PHP compare values in a single array and output the difference

I have an array that looks like this:
$rowarray(
[0] => [PID] => 97162 [TID] => 340 [StatsID] => 49678
[1] => [PID] => 97165 [TID] => 340 [StatsID] => 49673
[2] => [PID] => 97167 [TID] => 340 [StatsID] => 49675
[3] => [PID] => 97162 [TID] => 340 [StatsID] => 49679
)
Then my code looks like this:
$cntr=0;
foreach($rowarray as $row)
{
echo "<tr><td>$row[PID] $row[TID] $row[StatsID] </td></tr>";
$cntr++;
}
Two things I want to do I want to be able not print the duplicates in the array but print the additional column that has a different value. So my desired output would look like this.
97162 340 49678 49679
97165 340 49673
97167 340 49675
I started out with the array_unique() but that only returned:
97162 340 49678
Assuming only the StatsID changes (not clear from the question)
$map = array();
foreach($rowarray as $row){
$k = $row["PID"] . '-' . $row["TID"];
if( !isset( $map[$k] ) ){
$map[$k] = array();
}
array_push( $map[$k], $row["StatsId"] );
}
foreach($map as $k=>$v){
$row = explode( '-', $k );
echo "<tr><td>$row[0] $row[1] " . implode( " ", $v ) . " </td></tr>";
}
Here's what I'd do:
Start by sorting the array (using usort to sort by PID, then by TID)
Initialize "last" variables ($last_PID and $last_TID). They will store the respective values in the loop
In the loop, first compare the "current" variables to the "last" ones, if they're the same then just echo the StatsID value.
If they're not the same, output the <tr> (but not the final </tr>, so the first part of the loop can add more StatsID values if necessary)
Still inside the loop, after outputting everything, update the "last" variables.
After the loop, output the final </tr>
This may not be optimal, but I'm pretty sure it'll work.
Transfer the $rowarray structure into a map of maps of arrays, like this:
$rowarray = array(
array('PID' => 97162, 'TID' => 340, 'StatsID' => 49678),
array('PID' => 97165, 'TID' => 340, 'StatsID' => 49673),
array('PID' => 97167, 'TID' => 340, 'StatsID' => 49675),
array('PID' => 97162, 'TID' => 340, 'StatsID' => 49679)
);
$keys = array();
foreach ($rowarray as $row) {
if (!is_array(#$keys[$row['TID']])) {
$keys[$rowarray['TID']] = array();
}
if (!is_array(#$keys[$row['TID']][$row['PID']])) {
$keys[$row['TID']][$row['PID']] = array();
}
$keys[$row['TID']][$row['PID']][] = $row['StatsID'];
}
foreach ($keys as $pid => $pid_arr) {
foreach ($pid_arr as $tid => $tid_arr) {
echo "<tr><td>$tid $pid " . implode(' ', $tid_arr) . "</td></tr>";
}
}
See this code in action
As far as I can tell, the only way to do this would be to loop through the array creating a new unique array as you go.
$unique = array();
foreach ($row as $value)
{
$key = $value['PID'];
if (isset($unique[$key]))
{
$unique[$key]['StatsID'] .= ' ' . $value['StatsID'];
}
else
{
$unique[$key] = $value;
}
}
Now, $unique would give you the results you're looking for and you can loop through the unique array and output your results (I also added your counter if needed):
$count = count($unique);
foreach ($unique as $row)
{
echo "<tr><td>{$row['PID']} {$row['TID']} {$row['StatsID']} </td></tr>";
}

Algorithm to dynamically merge arrays [duplicate]

This question already has answers here:
Two arrays in foreach loop
(24 answers)
Closed 6 months ago.
I'm trying to create a INSERT statement for every row in a PHPExcel object. As I've struggled to iterate across the column (ie. go B1 C1 D1, get the values, and put them into an array), I've opted to get all the values for each column and put them into a multi-dimensional array that looks like this:
Array
(
[foo] => Array
(
[0] => 250
[1] => 247
[2] => 279
[3] => 249
)
[bar] => Array
(
[0] => AM PROV
[1] => AM PROV
[2] => AM PENS
[3] => AM PROV
)
[schoo] => Array
(
[0] => xxxx
[1] => yyy
[2] => zzz
[3] => aaa
)
)
I want to merge each of the arrays so that all the data at index 0 is in one array, etc. I've built a generic tool to allow you to select the columns you want from an uploaded spreadsheet. It needs to first merge the column data into a single array and then it should generate INSERT statements for each of the arrays. So the final deliverable is this:
INSERT INTO (foo, bar, schoo) VALUES (250, "AM PROV", "xxxx");
All help appreciated.
UPDATE: Hey all, thank you very much for your answers. I finally managed to get it working using row and cell iterators as per Mark's suggestion and it's working. I have a separate issue with it now, but I think it's something I can solve. Thanks again.
<?php
$uberArray = array(
"foo" => array(
0 => 250,
1 => 247,
2 => 279,
3 => 249,
),
"bar" => array(
0 => "AM PROV",
1 => "AM PROV",
2 => "AM PENS",
3 => "AM PROV",
),
"schoo" => array(
0 => "xxxx",
1 => "yyy",
2 => "zzz",
3 => "aaa",
)
);
$yourMysqlLink = mysql_connect('localhost', 'user', 'pass');
mysql_query('SET NAMES utf8'); // Adjust according to your encoding
$colNames = array_keys($uberArray);
$stringCols = array('bar', 'schoo');
$sqlInsertStr = 'INSERT INTO `your_table` (`'.implode('`, `', $colNames)."`) VALUES \n";
$rows = array();
// Not really for iterating the first array, we just need a loop
foreach ($uberArray[$colNames[0]] as $k => $v) {
$vals = array();
foreach ($colNames as $v2) {
$val = $uberArray[$v2][$k];
if (in_array($v2, $stringCols)) {
$val = "'".mysql_real_escape_string($val, $yourMysqlLink)."'";
}
$vals[] = $val;
}
$rows[] = "\t(".implode(', ', $vals).")";
}
$sqlInsertStr .= implode(",\n", $rows).';';
echo '<pre style="clear:both;">'.$sqlInsertStr.'</pre>'; ;
Note that you may need to do a few adjustments for performance reasons, if $uberArray is big (e.g. splitting the insert string into chunks). Or you can convert the data to CSV and use MySQL LOAD DATA INFILE method, which is real fast.
Not sure if this is what you were after but...
<?php
# Given this array
$arrays = array(
'foo' => array(
0 => 250,
1 => 247,
2 => 279,
3 => 249
),
'bar' => array(
0 => 'AM PROV',
1 => 'AM PROV',
2 => 'AM PENS',
3 => 'AM PROV'
),
'schoo' => array(
0 => 'xxxx',
1 => 'yyy',
2 => 'zzz',
3 => 'aaa'
)
);
# This code generates...
$fields = array();
$inserts = array();
foreach ($arrays as $k => $v) {
$fields[] = $k;
}
for ($i = 0; $i < count($arrays[$fields[0]]); $i++) {
$vals = array();
foreach ($fields as $field) {
$vals[] = $arrays[$field][$i];
}
$inserts[] = 'INSERT INTO (' . implode(',', $fields) . ') VALUES ("' . implode('","', $vals) . '")';
}
# This array
/* $inserts = array(
'INSERT INTO (foo, bar, schoo) VALUES ("250", "AM PROV", "xxxx")',
'INSERT INTO (foo, bar, schoo) VALUES ("247", "AM PROV", "yyy")',
'INSERT INTO (foo, bar, schoo) VALUES ("279", "AM PENS", "zzz")',
'INSERT INTO (foo, bar, schoo) VALUES ("249", "AM PROV", "aaa")'
); */
var_dump($inserts);
Edit: Though I think you're missing a table name from your INSERT statements.
Edit2: You could shorten the code using array_keys like Frosty Z does and skip the first foreach.
$inputArray = array('a' => array(1, 2, 3), 'b' => array("X'", 'Y', 'Z'));
$finalArray = array();
// build array with appropriate data rows
$finalIndex = 0;
foreach($inputArray as $key => $row)
{
foreach($row as $value)
$finalArray[$finalIndex][] = $value;
$finalIndex++;
}
// format it as SQL insert queries
$fields = array_keys($inputArray);
foreach($finalArray as $row)
{
echo "INSERT INTO table (".implode(", ", $fields).") "
. " VALUES (".implode(", ", array_map("format_data", $row)).");\n";
}
function format_data($value)
{
// assuming you're using MySQL. Replace the escape function by
// the appropriate one
if (is_string($value))
return "'".mysql_real_escape_string($value)."'";
else
return $value;
}
You can use one of those strange spl iterators for this :)
$iter = new MultipleIterator(MultipleIterator::MIT_KEYS_ASSOC);
foreach ($uberArray as $colName => $colValues) {
$iter->attachIterator(new ArrayIterator($colValues), $colName);
}
foreach ($iter as $vals) {
print_r($vals);
//or $pdoStmt->execute($vals);
}
But really, a simple for loop is the tool to use here.
I see no reason to merge the array unless you feel like wasting memory. You've already probably made a copy of the data. This just inserts the data row by row.
$data = array('foo' => array(...), ... );
$fields = array('foo', 'bar', 'schoo');
$c = count($data[$fields[0]));
$base_sql = 'INSERT INTO tbl ('.implode(',', $fields).') VALUES ';
for ($i = 0; $i < $c; ++$i)
{
$row_data = array();
foreach ($fields as $field)
$row_data[] = "'".escape_func($data[$field][$i])."'";
$sql = $base_sql . '(' . implode(',', $row_data). ')';
db_query($sql);
}
I would actually use prepared statements.
And you really should try to figure out how to iterate through the original dataset in one pass.

Categories