I'm trying to parse a CSV file and as part of it I would like to remove leading/trailing whitespace from all of my cells. Since it's a CSV file it's formatted like a 2D array. Initially I tried:
foreach($csv as $row){
foreach($row as $cell){
$cell = trim($cell);
}
}
However the result was untrimmed.
Next I tried using array_map as suggested here.
$csv = array_map('trim', $csv);
This gave me back an array of empty rows. So I also tried
foreach($csv as $row){
$row = array_map('trim', $row);
}
Which like my first attempt didn't change anything.
Here's the CSV data I'm using as my input:
First Name,Last Name,Contact Method,Phone, Email
John,Doe,Email,1-XXX-XXX-XXXX, john#example.com
Jane,Doe,Phone Call,1-XXX-XXX-XXXX,jane#example.com
In particular I was trying to get my script to trim the leading space in the last cell of the first row (" Email" => "Email").
You are not modifying the original array when you do the trim. You should get the values by reference in the foreach loop.
foreach($csv as &$row){
foreach($row as &$cell){
$cell = trim($cell);
}
}
From the documentation:
In order to be able to directly modify array elements within the loop
precede $value with &. In that case the value will be assigned by
reference.
You need to reference $row in order to make changes to the array (note the &):
foreach($csv as &$row){
$row = array_map('trim', $row);
}
If you are seeing it like you put here,
" Email" => "Email"
you'll have to trim it from the key, can you show how you are assigning the named headers. Because I would trim it there, but using array_map('trim', $data) will remove the whitespace, I do that all day long.
Well to just clean the keys you can do,
$keys = array_map( 'trim', array_keys($data) );
$data = array_combine( $keys, $data );
$input = [
'parent' => [
'child' => ' element to be trimmed '
]
];
array_walk_recursive($input, function (&$item) {
if (!is_array($item)) {
$item = trim($item);
}
});
Related
I have an array like this,
$array = array(
1,2,3,'4>12','13.1','13.2','14>30'
);
I want to find any value with an ">" and replace it with a range().
The result I want is,
array(
1,2,3,4,5,6,7,8,9,10,11,12, '13.1', '13.2', 14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
);
My understanding:
if any element of $array has '>' in it,
$separate = explode(">", $that_element);
$range_array = range($separate[0], $separate[1]); //makes an array of 4 to 12.
Now somehow replace '4>12' of with $range_array and get a result like above example.
May be I can find which element has '>' in it using foreach() and rebuild $array again using array_push() and multi level foreach. Looking for a more elegant solution.
You can even do it in a one-liner like this:
$array = array(1,2,3,'4>12','13.1','13.2','14>30');
print_r(array_reduce(
$array,
function($a,$c){return array_merge($a,#range(...array_slice(explode(">","$c>$c"),0,2)));},
[]
));
I avoid any if clause by using range() on the array_slice() array I get from exploding "$c>$c" (this will always at least give me a two-element array).
You can find a little demo here: https://rextester.com/DXPTD44420
Edit:
OK, if the array can also contain non-numeric values the strategy needs to be modified: Now I will check for the existence of the separator sign > and will then either merge some cells created by a range() call or simply put the non-numeric element into an array and merge that with the original array:
$array = array(1,2,3,'4>12','13.1','64+2','14>30');
print_r(array_reduce(
$array,
function($a,$c){return array_merge($a,strpos($c,'>')>0?range(...explode(">",$c)):[$c]);},
[]
));
See the updated demo here: https://rextester.com/BWBYF59990
It's easy to create an empty array and fill it while loop a source
$array = array(
1,2,3,'4>12','13.1','13.2','14>30'
);
$res = [];
foreach($array as $x) {
$separate = explode(">", $x);
if(count($separate) !== 2) {
// No char '<' in the string or more than 1
$res[] = $x;
}
else {
$res = array_merge($res, range($separate[0], $separate[1]));
}
}
print_r($res);
range function will help you with this:
$array = array(
1,2,3,'4>12','13.1','13.2','14>30'
);
$newArray = [];
foreach ($array as $item) {
if (strpos($item, '>') !== false) {
$newArray = array_merge($newArray, range(...explode('>', $item)));
} else {
$newArray[] = $item;
}
}
print_r($newArray);
I'm doing something that is perhaps too long and strange to explain, but basically I've mapped a string in a complex way into an array in a way to make them jumbled up. This is an example of how it would look:
field[26][25]='x';
field[24][23]='z';
field[28][29]='y';
Now that I've successfully jumbled up the string in exactly the way I wanted, I need to reconstruct the linear result.
So I need to take row 1 of the array, and loop through all the elements in this row to combine them into a string. Then do the same thing with row 2 and so on to create one massive linear string.
How do I count how many rows and elements in those rows I have? For the life of me I cant even begin to find how to do this for multid arrays.
Kind regards
#u_mulder's got a solid answer there. For the number of elements, you'd just say:
$total = 0;
foreach( $matrix as $row ) $total += count($row);
For the concatenation of elements, you'd just say:
$concat = '';
foreach( $matrix as $row ) $concat .= implode('', $row);
Bob's your uncle. But really, is there a valid use case for such a strange mashup?
$field[26][25]='x';
$field[24][23]='z';
$field[28][29]='y';
$field_string = '';
array_walk_recursive ( $field , function($item, $key) use (&$field_string){
if(!is_array($item)){
$field_string .= $item;
}
});
echo $field_string;
Honestly, this is a little confusing. I may need more info but let me know if this helps
You can start with an empty string and use two nested foreach to iterate over lines and items on each line and append each item to the string:
$result = '';
foreach ($fields as $row) {
foreach ($row as $item) {
$result .= $item;
}
}
Or you can replace the entire inner foreach with $result .= implode('', $row);.
You can even replace the outer foreach with a call to array_map() then implode() the array produced by array_map() into a string:
$string = implode(
'',
array_map(
function (array $items) {
return implode('', $items);
},
$fields
)
);
I am trying to parse a csv file to insert the csv contents into my Database. After the data is parsed the array looks like
Array
(
[AirportCode
] => GKA
)
and i would like to extract the AirportCode GKA and insert it. Everything looks fine but the key and Value in the above array having line breaks.
Sample code:
foreach($data['csvData'] as $field)
{
print_r($field);
$AirportCode = str_replace(PHP_EOL, '', $field['AirportCode']);
echo $AirportCode ;
}
But the AirportCode is always returning empty. I just want to get-rid of those line breaks. Can someone help me...?
Untested
I'm not sure about str_replace() capabilities on recognizing newline characters by using the escape reference, but it's worth a shot.
However your airport code is returning nothing, because the actual key seems to have a \n (new line character) in.
function fixArrayKey(&$arr)
{
$arr=array_combine(array_map(function($str){
return str_replace("\n ","",$str);
},array_keys($arr)),array_values($arr));
foreach($arr as $key=>$val)
{
if(is_array($val)) fixArrayKey($arr[$key]);
}
}
For your array values however you could just use:
function fixArrayValue($arr)
{
$return = array();
foreach($arr AS $key => $value){
$return[$key] = rtrim($value, "\n");
}
return $return
}
there is no array key called 'AirportCode' the actual key has a line break in it.
I would create a clean array by looping through the key value pairs, and adding them to a new array:
$clean=array();
foreach($data['csvData'] as $key => $value){
$ckey = str_replace(array("\r", "\n"), '', $key);
$cvalue = str_replace(array("\r", "\n"), '', $value);
$clean[$ckey]=$cvalue;
}
var_dump($clean);
I have a row returned from DB and i need to change the specific markup characters used in cols to the right characters for the display:
$row = mysqli_fetch_array($res, MYSQLI_ASSOC); //the result of query is 1 row
$markup = array("#", "#", "&", "$"); // this is our markup
$meaning = array("↑", "↓", "(dil.)", "(conc.)"); // this is our meaning of the markup for the display
foreach ($row as $k => $v) { //for each element of the array we change one char for the other
$v = str_replace ($markup, $meaning, $v);
echo "<br>$v";
}
UPD now its getting more weird. I did a mistake by tracing if the str_replace before the change was made to array, i fixed it ant tracing shows that it works! But there is a specialised output of this array down below and it still appears with unreplaced characters!
$reagent_no = "reaction_l" . $i; // determining the column number, irrelevant to the issue
echo "<td>\n<h3>{$row[$reagent_no]}</h3></td>"; //output of the supposedly
//changed characters, but it still outputs the markup, as if i didnt do anything to the array previously
You are first printing the variable and then using the str_replace() function. Change it to:-
foreach ($row as $k => $v) { //for each element of the array we change one char for the other
$v = str_replace ($markup, $meaning, $v);
echo "<br>$v";
}
The problem is that the str_replace is executed after the echo.
Try:
foreach ($row as $k => $v) { //for each element of the array we change one char for the other
$v = str_replace ($markup, $meaning, $v);
echo "<br>$v";
}
I have an array $rows where each element is a row of 15 tab-delimited values. I want to explode $rows into a 2D array $rowData where each row is an array element and each tab-delimited value is assigned to a different array element. I've tried these two methods without success. I know the first one has a coding error but I do not know how to correct it. Any help would be amazing.
for ($i=0; $i<count($rows); $i++){
for ($j=0; $j<15; $j++){
$rowData = array([$i] => array (explode(" ", $rows[$j])));
}
}
foreach ($rows as $value){
$rowData = array( array (explode(" ", $rows[$value])));
}
$rowData = array();
foreach($rows as $value) {
$rowData[] = explode("\t", $value);
}
for ($j=0; $j<15; $j++) {
$rowData[$j] = explode("\t", $rows[$j]);
}
To expand: The problem with the following code:
$rowData = array([$i] => array (explode(" ", $rows[$j])));
is that you don't appear to know what the different things you've written mean precisely.
A call to array() returns a new array with the indicated elements. So array (explode(" ", $rows[$j])) yields an array with a single element, namely the array returned by explode(). And you're wrapping that in another call to array(), specifying the loop variable $i as the key corresponding to that element. Also, you're using the assignment symbol =, which means that every time you go through the loop, $rowData is being completely overwritten - what you wanted was to add new elements to it without getting rid of the old ones.