I need to write an array to a .csv file in PHP.
Example array:
$array = array(
"name" => "John",
"surname" => "Doe",
"email" => "nowhere#nowhere.com"
);
By using implode(",", $array), I get a result like this:
John,Doe,nowhere#nowhere.com
However, I need to also write the key of each element to the file.
The desired output is this:
name:John,surname:Doe,email:nowhere#nowhere.com
How would I achieve this?
Try this code:
$out = $sep = '';
foreach( $array as $key => $value ) {
$out .= $sep . $key . ':' . $value;
$sep = ',';
}
$csv = "";
foreach($array as $key => $data)
{
// be sure to add " in your csv
$csv .= '"'.$key.':'.$data.'",';
}
// and add a new line at the end
$csv .= "\n";
echo $csv;
The answers above outputs a trailing comma at the end. To correct this, I use the following function:
$array = array(
"name" => "John",
"surname" => "Doe",
"email" => "nowhere#nowhere.com"
);
function implodeKV($glueKV, $gluePair, $KVarray){
$t = array();
foreach($KVarray as $key=>$val) {
$t[] = $key . $glueKV . $val;
}
return implode($gluePair, $t);
}
echo implodeKV( ':' , ',' , $array);
// outputs name:John,surname:Doe,email:nowhere#nowhere.com
http://phpassist.com/2dde2#2
If you're using PHP 5.3+, then an anonymous function can make your code a lot cleaner, though a simple for loop has the best performance. (Using array_walk comes close though!)
I ran some tests with a few different approaches (using PHP 5.4.33):
function makeArray(&$a) {
$a = array();
for($i = 0; $i < 100000; $i++) {
$a[rand()] = rand();
}
return $a;
}
makeArray($array);
$before = microtime(true);
$result = implode(
",",
array_map(
function($k, $v) {
return "$k:$v";
},
array_keys($array),
$array
)
);
$after = microtime(true);
$dur = $after - $before;
echo "Array Map w/ anonymous function: {$dur}s<br>";
makeArray($array);
$before = microtime(true);
function kv_func($k, $v) {
return "$k:$v";
}
$result = implode(
",",
array_map(
"kv_func",
array_keys($array),
$array
)
);
$after = microtime(true);
$dur = $after - $before;
echo "Array Map w/ function: {$dur}s<br>";
makeArray($array);
$before = microtime(true);
array_walk(
$array,
function(&$v, $k) {
$v = "$k:$v";
}
);
$result = implode(
",",
$array
);
$after = microtime(true);
$dur = $after - $before;
echo "Array Walk w/ anonymous function: {$dur}s<br>";
makeArray($array);
$before = microtime(true);
$ff = true;
$sep = ",";
$out = "";
foreach($array as $key => $val) {
if($ff) $ff = false;
else $out .= $sep;
$out .= "$key:$val";
}
$after = microtime(true);
$dur = $after - $before;
echo "Foreach loop w/ loop flag: {$dur}s<br>";
makeArray($array);
$before = microtime(true);
$out = "";
foreach($array as $key => $val) {
$out .= "$key:$val,";
}
$out = substr($out, 0, -1);
$after = microtime(true);
$dur = $after - $before;
echo "Foreach loop + substr: {$dur}s<br>";
Results:
Array Map w/ anonymous function: 0.13117909431458s
Array Map w/ function: 0.13743591308594s // slower than anonymous
Array Walk w/ anonymous function: 0.065797805786133s // close second
Foreach loop w/ loop flag: 0.042901992797852s // fastest
Foreach loop + substr: 0.043946027755737s // comparable to the above
And just for kicks, I tried the for loop without correcting for the trailing comma. It didn't really have any impact:
Foreach loop w/ trailing comma: 0.044748067855835s
<?php
$array = array(
"name" => "John",
"surname" => "Doe",
"email" => "nowhere#nowhere.com"
);
foreach( $array as $key=>$data ) {
$output .= $comma . $key . ':' . $data;
$comma = ',';
}
echo $output;
?>
Related
I am trying to merge two strings in a specific way.
Essentially I need to merge the first two strings into a third with a pipe symbol between them then separated by commas:
$merge1 = "id1,id2,id3"
$merge2 = "data1,data2,data3"
Those two would become:
$merged = "id1|data1,id2|data2,id3|data3"
I hope this makes sense?
I mean there is no PHP function that can output what you need.
Code produced desired output could be
<?php
$merge1 = "id1,id2,id3";
$merge2 = "data1,data2,data3";
$merged = [];
$arr1 = explode(',', $merge1);
$arr2 = explode(',', $merge2);
foreach ($arr1 as $key => $val) {
$merged[] = $val . '|' . $arr2[$key];
}
echo implode(',', $merged);
// id1|data1,id2|data2,id3|data3
This script will help you
<?php
$merge1 = "id1,id2,id3";
$merge2 = "data1,data2,data3";
$merge1 = explode(",", $merge1);
$merge2 = explode(",", $merge2);
$final = [];
foreach ($merge1 as $index => $value) {
$final[] = $value . "|" . $merge2[$index];
}
$final = implode(",", $final);
print_r($final);
output
id1|data1,id2|data2,id3|data3
Try this.
<?php
$merge1 = "id1,id2,id3";
$merge2 = "data1,data2,data3";
$merge1 = explode(",",$merge1);
$merge2 = explode(",",$merge2);
$mergeArr = array_combine($merge1,$merge2);
$mergeStr = [];
foreach($mergeArr as $k => $v) {
$mergeStr[] = $k.'|'.$v;
}
$mergeStr = implode(",",$mergeStr);
echo $mergeStr;
?>
How do i explode a following string
$str = "ProductId=123, Name=Ancient Roots, Modern Pursuits, Country=India, City=Bangalore, Price=3368"
Such that output array will contain
[
"ProductId" => "123",
"Name" => "Ancient Roots, Modern Pursuits",
"Country" => "India",
"City" => "Bangalore",
"Price" => "3368"
]
I tried to explode by "comma", then each element again explode by "equal to" as.
$arr = explode(",", $str);
and again
$prodarr = explode("=", $arr[0]);
$product["ProductId"] = $prodarr[1]
But facing problem when another comma is exist in value like in name "Ancient Roots, Modern Pursuits"
Your structure is very weak for breaking. But you can still try to parse it.
First explode on =. You will have next key and current value.
Then loop these and explode on , and select last element for next key and all previous parts as value (sample):
<?php
$str = "ProductId=123, Name=Ancient Roots, Modern Pursuits, Country=India, City=Bangalore, Price=3368";
$chunks = explode('=', $str);
$keys = [];
$values = [];
foreach ($chunks as $i => $chunk) {
$parts = explode(',', $chunk);
if ($i != count($chunks) - 1) {
$keys[] = trim(array_pop($parts));
}
if ($i != 0) {
$values[] = implode(',', $parts);
}
}
var_dump(array_combine($keys, $values));
I played a little bit around. I used preg_match_all() to extract the Patterns which contain characters that are no , and no = followed by a = followed by characters that are no = followed by a , or end of line. here is the result:
$result = array();
preg_match_all('/([^=,]+=[^=]+)(,|$)/', $string, $matches);
foreach($matches[1] as $data){
$data = explode('=', $data);
$result[trim($data[0])] = trim($data[1]);
}
$result = json_encode($result);
The result is:
{"ProductId":"123","Name":"Ancient Roots, Modern Pursuits","Country":"India","City":"Bangalore"}
Try something like this
<?php
$str = "ProductId=123, Name=Ancient Roots, Modern Pursuits, Country=India, City=Bangalore, Price=3368";
$str_arr = explode(",", $str);
$json_array = array();
for ($i = 0; $i < sizeof($str_arr); $i++)
{
if (isset($str_arr[$i + 1]))
{
if (strpos($str_arr[$i + 1], '=') !== false)
{
$prod = explode("=", $str_arr[$i]);
$json_array["" . $prod[0] . ""] = "" . $prod[1] . "";
}
else
{
$textAppend = "," . $str_arr[$i + 1];
$prod = explode("=", $str_arr[$i]);
$json_array["" . $prod[0] . ""] = "" . $prod[1] . "" . $textAppend . "";
$i++;
}
}
else
{
$prod = explode("=", $str_arr[$i]);
$json_array["" . $prod[0] . ""] = "" . $prod[1] . "";
}
}
var_dump($json_array);
?>
I would like to concatenate each element of array to next one. I want the output array to be:
Array
(
[0] => test
[1] => test/test2
[2] => test/test2/test3
[3] => test/test2/test3/test4
)
I tried the following way which concatenates each string to itself:
$url = preg_split("/[\s\/]+/", "test/test2/test3/test4");
foreach ($url as $dir) {
$dir .= $dir;
}
Any help appreciated.
Maybe another way
<?php
$data = array( 'test', 'test2', 'test3', 'test4' );
for( $i = 0; $i < count( $data ); $i++ )
{
if( $i != 0 )
{
$new[ $i ] = $new[ $i - 1 ] .'/'. $data[ $i ];
}
else
{
$new[ $i ] = $data[ $i ];
}
}
var_dump( $new );
Output
array(4) {
[0]=>
string(4) "test"
[1]=>
string(10) "test/test2"
[2]=>
string(16) "test/test2/test3"
[3]=>
string(22) "test/test2/test3/test4"
}
You should obtain the result you need in $my_array
$url = explode("/", "test/test2/test3/test4");
$str ='';
foreach($url as $key => $value){
if ( $str == '') {
$str .= $str;
} else {
$str .= '/'.$str;
}
$my_array[$key] = $str ;
echo $str . '<br />';
}
var_dump($my_array);
$url = preg_split("/[\s\/]+/", "test/test2/test3/test4");
$arr = array();
$str = '';
foreach ($url as $key => $dir) {
if ($key !== 0) {
$str .= '/' . $dir;
} else {
$str .= $dir;
}
$arr[] = $str;
}
On each iteration concate a string with new value and add it as a separate value for your output array.
Here's a quick way. For simple splitting just use explode():
$url = explode("/", "test/test2/test3/test4");
foreach($url as $value) {
$temp[] = $value;
$result[] = implode("/", $temp);
}
Each time through the loop, add the current value to a temporary array and implode it into the next element of the result.
I have an associative array in php, for example with the values:
"apple" => "green"
"banana" => "yellow"
"grape" => "red"
My question is, how can I write the keys and values for this array to a .txt file into two perfect columns?
By which I mean into two columns with a uniform distance between them all the way down
You can use str_pad() php function for the output.
http://php.net/manual/en/function.str-pad.php
Code:
<?php
$fruits = array( "apple" => "green",
"banana" => "yellow",
"grape" => "red" );
$filename = "file.txt";
$text = "";
foreach($fruits as $key => $fruit) {
$text .= str_pad($key, 20)." ".str_pad($fruit, 10 )."\n"; // Use str_pad() for uniform distance
}
$fh = fopen($filename, "w") or die("Could not open log file.");
fwrite($fh, $text) or die("Could not write file!");
fclose($fh);
Output:
apple green
banana yellow
grape red
// Getting the length dynamically version.
<?php
$fruits = array( "apple" => "green",
"banana" => "yellow",
"grape" => "red" );
$filename = "file.txt";
$maxKeyLength = 0;
$maxValueLength = 0;
foreach ($fruits as $key => $value) {
$maxKeyLength = $maxKeyLength < strlen( $key ) ? strlen( $key ) : $maxKeyLength;
$maxValueLength = $maxValueLength < strlen($value) ? strlen($value) : $maxValueLength ;
}
$text = "";
foreach($fruits as $key => $fruit) {
$text .= str_pad($key, $maxKeyLength)." ".str_pad($fruit, $maxValueLength )."\n"; //User str_pad() for uniform distance
}
$fh = fopen($filename, "w") or die("Could not open log file.");
fwrite($fh, $text) or die("Could not write file!");
fclose($fh);
Maybe a long shot, but you could possible do something like find the max array key length and then use that as a guide for how many spaces you want in between the words.
eg.
You could get the max array key length using strlen() like this:
$maxLength = 0;
foreach($array as $key => $item){
if(strlen($key) > $maxLength){
$maxLength = strlen($key);
}
}
$maxLength += 5; //or any spacing value here
And then use str_pad() to add padding to the word like this:
$str = '';
foreach($array as $key => $item){
$str .= str_pad($key, $maxLength, ' ', STR_PAD_RIGHT) . $item . '\n'; //add padding to the right hand side of the word with spaces
}
file_put_contents('path/to/file', $str);
This probably isn't the best solution but you could probably make it more efficient.
Update
I revised the functionality, and the below will work with a string (array key) of any length.
$longest = 0;
// find the longest string.
foreach ($array as $key => $val) {
$c = strlen($key);
$longest = ($c > $longest) ? $c : $longest;
}
$distance = 5;
$str = '';
// now loop through and apply the appropriate space
foreach ($array as $key => $val) {
$c = strlen($key);
$space = $distance + ($longest - $c);
$str .= $key . str_repeat(" ", $space) . $val . "\n";
}
echo $str;
Example
I don't understand why you'd want to do something like this, but this will do as you desire:
$str = '';
foreach($array as $key => $item){
$str .= $key . "\t" .$item ."\n";
}
file_put_contents('path/to/file', $str);
Example
You'd obviously have to test the file_put_contents() to ensure it succeeded, but I'll leave that to you.
You'd just have to change the ammount of tabs (\t) if you run into any long strings. In your case, it'd probably be best if you went with 2 (\t\t).
$Offer is your array
$file = 'people.txt';
$content = '';
foreach ($Offer as $key => $value) {
$content .= $key.'='.$value;
// Write the contents back to the file
file_put_contents($file, $current);
}
I want to combine strings in PHP. My script creates every possible combination like below.
$part1 = array('','d','n','s','g');
$part2 = array('a','e','o','oo');
$part3 = array('m','n','s','d','l','t','g','j','p');
$part4 = array('g','p','l','');
$part5 = array('g','p','l');
$part6 = array('a','e','o');
$part7 = array('d','l','r','');
$names = array();
foreach ($part1 as $letter1) {
foreach ($part2 as $letter2) {
foreach ($part3 as $letter3) {
foreach ($part4 as $letter4) {
foreach ($part5 as $letter5) {
foreach ($part6 as $letter6) {
foreach ($part7 as $letter7) {
$names[] = $letter1 . $letter2 . $letter3 . $letter4 . $letter5 . $letter6 . $letter7;
}
}
}
}
}
}
}
But I am not happy with my solution. I is quick and dirty code. Is there a solution wich works with a flexible number of part arrays, so I can extend the script by e.g. $part8 easiely? (without changing the loop construction)
Recursive one:
function buildNames( $parts, $chars = ''){
// Nothing to do, shouldn't happen
if( !count( $parts)){
return array();
}
$names = array();
$part = array_shift( $parts);
// Max level, we can build final names from characters
if( !count( $parts)){
foreach( $part as $char){
$names[] = $chars . $char;
}
return $names;
}
// "We need to go deeper" and build one more level with remembered chars so far
foreach( $part as $char){
$names = array_merge( $names, buildNames( $parts, $chars . $char));
}
return $names;
}
$parts = array( $part1, $part2, $part3, $part4, $part5, $part6, $part7);
$names = buildNames( $parts);
From head, from scratch, comment if something, but idea should be good
You could reduce this problem to six cartesian products:
cartesianProduct($part1,
cartesianProduct($part2,
cartesianProduct($part3,
cartesianProduct($part4,
cartesianProduct($part5,
cartesianProduct($part6, $part7))))));
function cartesianProduct($p1, $p2) {
$ret = array();
foreach($p1 as $l1)
foreach($p2 as $l2)
$ret[] = $l1 . $l2;
return $ret;
}