I have a csv file which I am trying to turn into a different structured array. First, I turn it into an array named all_data() constructed like this:
$data = file_get_contents($id . '.csv');
$data_array = explode("\n", $data);
foreach($data_array AS $data){
$all_data[] = explode("\t", $data);
}
results look like this:
array(5) {
[0]=>
array(2) {
[0]=>
string(10) "2012-11-14"
[1]=>
string(2) "10"
}
[1]=>
array(2) {
[0]=>
string(10) "2012-11-14"
[1]=>
string(2) "10"
}
[2]=>
array(2) {
[0]=>
string(10) "2012-11-14"
[1]=>
string(2) "10"
}
[3]=>
array(2) {
[0]=>
string(10) "2012-11-14"
[1]=>
string(2) "10"
}
[4]=>
array(1) {
[0]=>
string(0) ""
}
}
And then I turn it into im_arr() with the following code:
foreach($all_data as $key => $value){
$im_arr[$key][$value[0]] = $value[1];
}
The results:
array(5) {
[0]=>
array(1) {
["2012-11-14"]=>
string(2) "10"
}
[1]=>
array(1) {
["2012-11-14"]=>
string(2) "10"
}
[2]=>
array(1) {
["2012-11-14"]=>
string(2) "10"
}
[3]=>
array(1) {
["2012-11-14"]=>
string(2) "10"
}
[4]=>
array(1) {
[""]=>
NULL
}
}
And then, finally another foreach loop gives me the results I am looking for:
foreach ($im_arr as $val) {
foreach ($val as $key => $val2) {
$im_data[$key]=$val2;
}
}
With the result for im_data() being:
array(2) {
["2012-11-14"]=>
string(2) "10"
[""]=>
NULL
}
Which would be perfect, since the array im_data() is exactly what I would like to get out of all_data(). However, when I am trying to put this code in another part of the program it doesn't work, and I am thinking it might be because of the warnings I receive:
"PHP Notice: Undefined offset: 1 in ... on line 93"
Line 93 corresponds to this line:
$im_arr[$key][$value[0]] = $value[1];
Here is the complete part of the code:
$all_data = array();
$im_arr=array();
$data = file_get_contents($id . '.csv');
$data_array = explode("\n", $data);
foreach($data_array AS $data){
$all_data[] = explode("\t", $data);
}
foreach($all_data as $key => $value){
$im_arr[$key][$value[0]] = $value[1]; //the line for the error
}
$im_data=array();
foreach ($im_arr as $val) {
foreach ($val as $key => $val2) {
$im_data[$key]=$val2;
}
}
var_dump($im_data);
I know there are many many questions posted for this same error, but I couldn't figure out the problem with this particular piece of code.
This is the problem:
[4]=>
array(1) {
[0]=>
string(0) ""
}
Just check that the data is set, and isn't empty before adding them to $im_arr:
foreach ($all_data as $key => $value) {
if (isset($value[0]) && isset($value[1]) && !empty($value[0]) && !empty($value[1])) {
$im_arr[$key][$value[0]] = $value[1];
}
}
For every foreach i would pre-check if the first argument is an array
For instance ;
//Just add line below for every foreach (and add any required else statement if needed)
if(is_array($im_arr))
foreach ($im_arr as $val) {
if(is_array($val))
foreach ($val as $key => $val2) {
$im_data[$key]=$val2;
}
}
Related
I have an array like that:
array(5) {
["code"]=>
int(1)
["messageError"]=>
string(27) "La typologie est incorrecte"
["model"]=>
string(3) "lot"
["grp_regles"]=>
array(1) {
[0]=>
array(1) {
[0]=>
array(3) {
["champ"]=>
string(21) "lot_surface_habitable"
["comparaison"]=>
string(7) "between"
["valeurAttendue"]=>
array(2) {
[0]=>
int(16)
[1]=>
int(40)
}
}
}
}
["prerequis"]=>
array(2) {
[0]=>
array(3) {
["champ"]=>
string(6) "typ_id"
["comparaison"]=>
string(1) "="
["valeurAttendue"]=>
int(1)
}
[1]=>
array(3) {
["champ"]=>
string(22) "tranche.fus.fup.fup_id"
["comparaison"]=>
string(1) "="
["valeurAttendue"]=>
int(1)
}
}
}
I want to do a foreach in "prerequis":
$modelRetrieve = $this->retrieveModel($model);
$modelFind = $modelRetrieve::find($id);
$arrayError=[];
$query = '';
$path = storage_path() . "/json/controle.json";
$json = file_get_contents($path);
foreach (json_decode($json,true) as $key => $value) {
$test = true;
var_dump($value);
if($value['model'] === $model ){
foreach ($value['prerequis'] as $key => $value2) {
if( $test && $modelFind[$value2['champ']] == (int)$value2["valeurAttendue"] )
{
$test = true;
}
}
}
}
I need in second foreach to use in $value2['champ'] where $value2['champ'] is "tranche.fus.fup_id. So I need to explode that to have ['tranche']['fus']['fup_id'].
How to use explode with that ?
thanks everyone :)
you can use laravel data_get helper:
data_get($value2, $value2['champ'])
To nest the $segments of the string starting with the innermost item of the result, we have to array_reverse() the $segments so we can loop over it and wrap each iteration's result with another array level in the next iteration until we looped through the whole $segments array.
$exploded = array_reduce(array_reverse(explode('.', $value2['champ'])), function($res, $segment) {
return [ $segment => $res ];
}, []);
I have this array:
array(5) {
[0]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "1"
["productTxtVal"]=>
string(5) "Text1"
}
[1]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "2"
["productTxtVal"]=>
string(5) "Text2"
}
[2]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "3"
["productTxtVal"]=>
string(5) "Text3"
}
[3]=>
array(4) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTextSeq"]=>
string(1) "1"
["productTxtVal"]=>
string(5) "Text1"
}
[4]=>
array(4) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTextSeq"]=>
string(1) "2"
["productTxtVal"]=>
string(5) "Text2"
}
}
With the above input, I want the output array to look like this:
array(2) {
[0]=>
array(3) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTxtVal"]=>
string(17) "Text1 Text2 Text3"
}
[1]=>
array(3) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTxtVal"]=>
string(11) "Text1 Text2"
}
}
The resulting array does not need the productTextSeq key, just the combined values of productTextVal, when the productCode is the same. I've searched SO for examples of this but it seems every example I've found are based on multiple input arrays. I know I can brute force this with nested foreach functions but would love a more elegant solution.
I ended up just doing it the brute force method, here is my solution if anyone's interested:
$productData = array();
$sortedData = array();
$comments = '';
$saveKey = '';
$appendComment = false;
$idx = 0;
foreach ($data as $key=>$value) {
foreach ($value as $k=>$v) {
if ($k == 'productCode') {
if ($v == $saveKey) {
$appendComment = true;
} else {
$appendComment = false;
$saveKey = $v;
if ($idx !== 0) { // Don't write to array on first iteration!
$productData['productTxtVal'] = $comments;
$sortedData[] = $productData;
}
}
}
if ($k == 'productTxtVal') {
if ($appendComment == true) {
$comments .= ' ' . trim($v);
} else {
$comments = trim($v);
}
}
}
$productData = $value;
$idx++;
}
Not "elegant" but it works. I also have a check after this logic in case only one productCode is in the original array, as it won't be written to the $sortedData array since the key never changes.
The following code assumes you control the contents of the original data array (due to risk of injection using extract() function) and that no 2 items with the same productCode have the same productTextSeq.
$products = [];
foreach ($data as $item) {
// extract contents of item array into variables
extract($item);
if (!isset($products[$productCode])) {
// create product array with code, upc, text as array
$products[$productCode] = compact('productCode', 'productUPC') + ['productTxtVal' => []];
}
// add text value to array with sequence as index
$products[$productCode]['productTxtVal'][$productTextSeq] = $productTxtVal;
}
$products = array_values( // ignore array keys
array_map(function($product) {
ksort($product['productTxtVal']); // sort text as array by index/ sequence
$product['productTxtVal'] = implode(' ', $product['productTxtVal']); // implode into string
return $product;
}, $products)
);
You can run the code here: https://repl.it/BWQL
Guys i've got an array thats like this:
array(3) {
[2]=>
array(1) {
["name"]=>
array(2) {
[0]=>
string(13) "row1"
[1]=>
string(13) "row3"
}
}
[5]=>
array(1) {
["name"]=>
array(2) {
[0]=>
string(15) "row1"
[1]=>
string(15) "row3"
}
}
[3]=>
array(1) {
["name"]=>
array(2) {
[0]=>
string(13) "row1"
[1]=>
string(13) "row3"
}
}
What i want to achieve is make foreach loop the 0 elements (row1) and then loop through 1 (row3) and go on like this. Is there a way to do that?
You could try to rebuild the array:
$rows = array();
foreach($array as $subarray)
foreach($subarray as $key => $value)
$rows[$key][] = $value;
At this point al the same subelements from the array are together in a new array, and now you can easy loop over a subelement:
foreach($rows as $key => $value)
echo 'processing row: ' . $key ' with value ' . $value;
I found a different approach to this problem, the JvdBeg solution is working wonderful, but if someone is stuck in a similar situations, this is how i did it:
$key = key($arr);
$keys = array_keys($arr);
for ($i=0;$i<sizeof($arr[$key]['index']);$i++) {
for($k=0;$k<sizeof($arr);$k++) {
$key = $keys[$k];
echo "\n";
}
}
I'm trying to add another column of data to each row in a foreach loop. It's purpose is to remember the element of data importeded from XML processed to an multidimensional array. It's stuck as a scalar though the var_dumps looks fine.
<?php
$KEY = 0;
foreach ($eventsArray as $keyMe){
$thisKey['KEY'][0] = strval($KEY);
$keyedArray = array_merge($keyMe, $thisKey);
$KEY++;
}
// Prep for multisort
foreach ($keyedArray as $key => $value){
$date[$key] = $value['DATE'];
$title[$key] = $value['TITLE'];
$link[$key] = $value['LINK'];
$slide[$key] = $value['SLIDE'];
$location[$key] = $value['LOCATION'];
$time[$key]= $value['TIME'];
$KEY[$key] = $value['KEY']; // Warning: Cannot use a scalar value as an array
}
/* var_dump(
array(7) {
["DATE"]=> array(1) { [0]=> string(10) "2012-12-18" }
["TITLE"]=> array(1) { [0]=> string(20) "Event Title" }
["LINK"]=> array(1) { [0]=> string(38) "aLinkLocation.htm" }
["SLIDE"]=> array(1) { [0]=> string(2) "16" }
["LOCATION"]=> array(1) { [0]=> string(8) "Location of Event" }
["TIME"]=> array(1) { [0]=> string(3) "8am" }
["KEY"]=> array(1) { [0]=> string(2) "23" }
}
*/
array(2) {
["names"]=> array(4) {
[0]=> string(4) "Edit"
[1]=> string(6) "Delete"
[2]=> string(8) "Activate"
[3]=> string(10) "Deactivate"
}
["action"]=> array(4) {
[0]=> string(4) "ajax"
[1]=> string(4) "abc"
[2]=> string(4) "def"
[3]=> string(4) "xyz"
}
}
How do i loop through this in a single foreach loop?
Assuming both arrays are of the same size and have the same keys:
foreach($array['names'] as $k => $name) {
$action = $array['actions'][$k];
// do whatever you want to do with $name and $action
}
$newArr = array();
foreach($data['names'] as $i => $val) {
$newArr[$val] = $data['actions'][$i];
}
Or if you want a one liner at that
$newArr = array_combine($data['names'], $data['action']);
I guess the best way is a recursive function which can move through even three dimensions and more
function MoveThroughArray($arr)
{
foreach($arr as $value)
{
if(is_array($value))
MoveThroughArray($value);
else
// Do Something
}
}