How can I split a huge array into chunks? - php

I am parsing about 500.000 entries into an array $properties:
$properties = array();
$handle = fopen($file_path, "r");
if ($handle) {
while (($str = fgets($handle)) !== false) {
if (strlen($str) && $str[0] == '#') {
$pdate = substr($str, 1);
$date = rtrim($pdate);
$formatted = DateTime::createFromFormat('* M d H:i:s T Y',$date);
}
$str = rtrim ($str, "\n");
$exp = explode ('=', $str);
if(count($exp) == 2){
$exp2 = explode('.', $exp[0]);
if( count($exp2) == 2 ) {
if($exp2[1] == "dateTime"){
$s = str_replace("\\","",$exp[1]);
$d = strtotime($s);
$dateTime = date('Y-m-d H:i:s', $d);
$properties [$exp2[0]][$exp2[1]] = $dateTime;
} else {
$properties [$exp2[0]][$exp2[1]] = $exp[1];
}
} else {
$properties [$exp[0]] = $exp[1];
}
}
}
fclose($handle);
} else {
echo "error";
}
This is working well so far. But I need to split the array into chunks, because otherwise the array is too big to work with it:
$properties_chunk = array_chunk($properties,10000,true);
But now I have the problem that the $properties_chunk array is not created. The system crashes. This is too much. But what can I do now?
The array should look like this in the end:
array(4) {
[0]=>
array(10000) {
["12345"]=>
array(5) {
["dateTime"]=>
string(19) "2016-10-12 19:46:25"
["fileName"]=>
string(46) "monkey.jpg"
["path"]=>
string(149) "Volumes/animals/monkey.jpg"
["size"]=>
string(7) "2650752"
}
["678790"]=>
array(5) {
["dateTime"]=>
string(19) "2016-10-12 14:39:43"
["fileName"]=>
string(45) "elephant.jpg"
["path"]=>
string(171) "Volumes/animals/elephant.jpg"
["size"]=>
string(7) "2306688"
}
... and so on.

If you use array_splice the items will be moved from the input array to the resulting array.
This should mean the memory use should stay the same-ish.
This will do the same as array_chunk but hopefully be less memory hungry.
$arr = [1,2,3,4,5,6,7,8,9,10];
$n = 10000;
$count = (count($arr)/$n)-1; // do not splice the last items in loop
For($i=0; $i<$count; $i++){
$res[] = array_splice($arr, 0,$n);
}
$res[] = array_splice($arr, 0,count($arr));
// here we splice the last items from arr to $res.
// Notice how we splice count($arr) instead of $n.
// If count($arr) == $n we could have done it in the loop.
// But if we assume they are not, array_splice in the loop will create empty items. This line will not.
Var_dump($res, $arr); // $res has all values, $arr is empty
https://3v4l.org/XDpdI

Related

Add new values ​to an array if preg_match found match recursively with php

how to add a new value to a multidimensional array keeping the key if preg_match found a match with the files in my directory ?
<?php
if(isset($_POST['submit'])){
$txt1 = $_FILES['filetxt']['tmp_name'];
$txt2 = $_FILES['filetxt']['name'];
$g = glob('./upload/img/*.*');
foreach ($txt2 as $var) {
$rap = explode(' ', $var);
$zc = count($rap);
for ($i=0; $i < $zc; $i++) {
$str = $rap[$i];
$ext = substr($str, 0, strrpos($str, "."));
$pattern = "/$ext/i";
if(preg_match_all($pattern, $str, $matches)) {
$array = array_map('array_filter', $matches);
$array = array_filter($array);
}
}
var_dump($array);
}
}
Here's result of $array (pattern for preg_match):
array(1) {
[0]=>
string(12) "dropshipping"
}
array(1) {
[0]=>
string(9) "standards"
}
array(1) {
[0]=>
string(8) "boutique"
}
array(1) {
[0]=>
string(7) "vitrine"
}
I would like to apply preg_match on each value of the txt2 array and recursively insert the corresponding values ​​if the condition is true.
here's result of txt2 array:
array(4) {
[0]=>
string(22) "Texte dropshipping.txt"
[1]=>
string(24) "Texte site standards.txt"
[2]=>
string(22) "Texte sur boutique.txt"
[3]=>
string(30) "Texte sur les site vitrine.txt"
}

Query arrays using php

I have an array of imported data:
array(3) {
[1234]=>
array(2) {
["item"]=>
string(6) "scotch"
["type"]=>
string(6) "Spirit"
}
[5678]=>
array(2) {
["item"]=>
string(4) "wine"
["type"]=>
string(7) "Vintner"
}
[9012]=>
array(2) {
["item"]=>
string(11) "soft drinks"
["type"]=>
string(3) "Pop"
}
}
I'm trying to make it say "Its in the Spirit section under code 1234"
I'm new to php so not sure I'm writing the for loop if function correctly. I keep getting "We are out of stock". Man I need a whisky. Help please
my code:
<?php
$row = 1;
$sheet1 = [];
if (($handle = fopen("sheet1.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$sheet1[$data[0]] = [];
$sheet1[$data[0]]['item'] = $data[1];
$sheet1[$data[0]]['type'] = $data[2];
$row++;
}
fclose($handle);
}
var_dump($sheet1);
$string = 'Where is scotch in shop';
echo $string;
$words = explode(' ', $string);
print_r($words);
for ($i = 0; $i < count($words); ++$i) {
if (isset($sheet1[$words[$i]]['item'])) {
echo "Its in the ".$sheet1[$words[$i]]['type']." section marked
under code ".$sheet1[$words[$i]]['key'];
}
}
echo "We are out of stock";
?>
If you change it to a foreach and then check for the existance of the word using in_array() it all looks a litle easier to understand.
foreach ($sheet1 as $key=>$sheet) {
if ( in_array($sheet['item'], $words) ) {
echo "Its in the {$sheet['type']} section marked under code $key";
}
}
Result
Its in the Spirit section marked under code 1234

How can I turn a value of an array into the key of an array?

I am parsing a text file that looks more or less like this:
123.animal=cat
123.name=fred
123.food=fish
345.animal=dog
petshop=zoonoria
This is how I am parsing it:
$file_path = $filename;
$linesArray = file($file_path);
$properties = array();
foreach ($linesArray AS $line) {
if (strlen($line) && $line[0] == '#') {
$pdate = substr($line, 1);
$date = rtrim($pdate);
$formatted = DateTime::createFromFormat('* M d H:i:s T Y',$date);
}
if (false !== ($pos = strpos($line, '='))) {
$prop=array();
$prop[trim(substr($line, 0, $pos))] = trim(substr($line, $pos + 1));
$lineContArray = explode("=", $line);
$identArray = explode(".", $lineContArray[0]);
$ident = $identArray[0];
$type = $identArray[1];
$value = trim($lineContArray[1]);
$found = 0;
for ($i=0; $i<count($properties); $i++) {
if ($properties['number'] == $ident) {
$properties[$i][$type]= $value;
$found=1;
break;
}
}
if ($found == 0) {
if (!empty($type)) {
$properties[] = array('number' => $ident, $type => $value);
} else {
$properties[] = array($ident => $value); }
}
}
My result is:
array(3) {
[0]=>
array(2) {
["number"]=>
string(3) "123"
["animal"]=>
string(3) "cat"
}
[1]=>
array(2) {
["number"]=>
string(3) "123"
["name"]=>
string(4) "fred"
}
[3]=>
array(2) {
["number"]=>
string(3) "345"
["animal"]=>
string(4) "dog"
}
[4]=>
array(1) {
["petshop"]=>
string(5) "zoonoria"
}
}
But I need the array to be different, this is the result I like to achieve:
array(3) {
[123]=>
array(3) {
["animal"]=>
string(3) "cat"
["name"]=>
string(4) "fred"
["food"]=>
string(4) "fish"
}
[345]=>
array(1) {
["animal"]=>
string(3) "dog"
}
[petshop]=>
string(8) "zoonoria"
}
}
So my main problem is, I do not know how to turn number into the key. I tried various things, but I failed. I am really happy for every hint.
I tried the solution of Svetlio:
$file_path = $filename;
$linesArray = file($file_path);
$properties = array();
foreach ( $linesArray as $str) {
$exp = explode ('=', $str);
if(count($exp) == 2){
$exp2 = explode('.', $exp[0]);
if( count($exp2) == 2 ) {
$properties [$exp2[0]][$exp2[1]] = $exp[1];
} else {
$properties [$exp[0]] = $exp[1];
}
} else {
}
}
My result:
array(3) {
["123"]=>
array(3) {
["animal"]=>
string(3) "cat
"
["name"]=>
string(4) "fred
"
["food"]=>
string(4) "fish
"
}
[345]=>
array(1) {
["animal"]=>
string(3) "dog
"
}
["petshop"]=>
string(3) "zoonoria
"
}
Here is working solution but it doesn't cover the cases where stings don't contain = or have more than 1 of them..
$strings = array(
'123.animal=cat',
'123.name=fred',
'123.food=fish',
'345.animal=dog',
'petshop=zoonoria'
);
$array = array();
foreach ( $strings as $str) {
// I accept that there is 1 = at strings possible
$exp = explode ('=', $str);
if(count($exp) == 2){
$exp2 = explode('.', $exp[0]);
if( count($exp2) == 2 ) {
$array[$exp2[0]][$exp2[1]] = $exp[1];
} else {
// if there are multiple/null dots i set the string as key
$array[$exp[0]] = $exp[1];
}
} else {
// what to do if there are no or many = = = in the string ?
}
}
var_dump($array);
After getting the result you can use array_reduce to get the desired result
$result = array_reduce($initialArray, function ($result, $item) {
$number = isset($item['number']) ? $item['number'] : end(array_keys($result));
if (!isset($result[$number])) {
$result[$number] = array();
}
foreach ($item as $key => $value) {
if ($key == 'number') continue;
$result[$number][$key] = $value;
}
return $result;
}, array());
foreach ($linesArray AS $line) {
if (strlen($line) && $line[0] == '#') {
$pdate = substr($line, 1);
$date = rtrim($pdate);
$formatted = DateTime::createFromFormat('* M d H:i:s T Y',$date);
}
if (false !== ($pos = strpos($line, '='))) {
$prop=array();
$prop[trim(substr($line, 0, $pos))] = trim(substr($line, $pos + 1));
$lineContArray = explode("=", $line);
$identArray = explode(".", $lineContArray[0]);
$ident = $identArray[0];
$type = $identArray[1];
$value = trim($lineContArray[1]);
$found = 0;
for ($i=0; $i<count($properties); $i++) {
if ($properties['number'] == $ident) {
$properties[$i][$type]= $value;
$found=1;
break;
}
}
if ($found) {
if ($type && $ident) {
$properties[$ident][$type] = $value;
} else if (!$type && $ident) {
$properties[$ident][] = $value;
}else if ($type && !$ident){
$properties[$type][] = $value;
}
}
$data = '123.animal=cat
123.name=fred
123.food=fish
345.animal=dog
petshop=zoonoria';
$ini = parse_ini_string($data);
$result = [];
foreach ($ini as $key => $value) {
$splitKey = explode('.', $key);
$iniPtr = &$result;
foreach($splitKey as $subKey) {
if (!isset($iniPtr[$subKey])) { $iniPtr[$subKey] = null; }
$iniPtr = &$iniPtr[$subKey];
}
$iniPtr = $value;
}
unset($iniPtr);
var_dump($result);
Demo
In your case, use $ini = parse_ini_file($file_path); to read your file data into $ini

Reading from CSV and merging content in rows into an array

pastebin link: http://pastebin.com/4YCdbrsP
Input CSV format,
number | itemid
1001, 121212
1001, 12991
1042, 99878
1042, 89776
1042, 87777
1045, 11010
1046, 22299
1049, 9875
Expected Output
[1001 => {121212,12991}]
[1042 => {99878, 89776, 87777}]
[1045 => {11010}]
[1046 => {22299}]
[1049 => {9875}]
I am trying to read each line from a CSV file which has contents as specified above (two columns, each row containing "number" as the first column and an associated "itemid" as the second column.
If the next line has the same "number" then, I would like its corresponding "itemid" to be pushed to an array. Repeat this, if the next line(s) have the same "number".
Following is where I have gotten so far.
$row = 0;
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE && $row < 8) {
$sku = $data[0];
$upc = $data[1];
$skuUpcList = array($sku => array());
array_push($skuUpcList[$sku], $upc);
$row++;
while(($data = fgetcsv($handle, 1000, ",")) !== FALSE && $row < 8) {
if($data[0] == $sku) {
array_push($skuUpcList[$sku], $data[1]);
$row++;
} else {
$sku = $data[0];
$upc = $data[1];
$skuUpcList = array($sku => array());
array_push($skuUpcList[$sku], $data[1]);
$row++;
}
$skuUpcList = array_unique($skuUpcList);
var_dump($skuUpcList);
echo '<br>';
}
}
=== Output of the above script ===
array(1) { [1001]=> array(2) { [0]=> string(6) "121212" [1]=> string(5) "12991" } }
array(1) { [1042]=> array(1) { [0]=> string(5) "99878" } }
array(1) { [1042]=> array(2) { [0]=> string(5) "99878" [1]=> string(5) "89776" } }
array(1) { [1042]=> array(3) { [0]=> string(5) "99878" [1]=> string(5) "89776" [2]=> string(5) "87777" } }
array(1) { [1045]=> array(1) { [0]=> string(5) "11010" } }
array(1) { [1046]=> array(1) { [0]=> string(5) "22299" } }
array(1) { [1049]=> array(1) { [0]=> string(4) "9875" } }
As you can see, even though the script runs fine, I am trying to make sure that the script echos each "number" only once but, as per the above output the "number" 1042 appears three times.
I have tried to move the var_dump() statement outside the 2nd while loop but, it doesn't seem to help.
Any help regarding this would be helpful.
pastebin link: http://pastebin.com/4YCdbrsP
$skuUpcList = array();
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$skuUpcList[$data[0]] []= $data[1];
}
This seems to work quite nicely:
<?php
$handle = fopen("xxx.csv", "r");
$row = 0;
$skuUpcList = array();
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE && $row < 8) {
$sku = $data[0];
$upc = $data[1];
if ( array_key_exists($sku, $skuUpcList) ) {
$skuUpcList[$sku][] = $upc;
} else {
$skuUpcList[$sku] = array($upc);
}
$row++;
}
print_r( $skuUpcList );

Setting value in array inside foreach loop PHP

Hello I am setting a key value pair in an array in a foreach loop
e.g
array(2) {
[0]=>
array(1) {
["resourceType"]=>
string(4) "File"
["resourceName"]=>
string(4) "Test"
[1]=>
array(1) {
["resourceType"]=>
string(4) "File"
["resourceName"]=>
string(4) "Test"
}
I am doing this via a foreach loop
foreach ($output as $data) {
$resourceType = strpos($data, "d");
if ($resourceType) {
$ftpArray[]['resourceType'] = "Folder";
} else {
$ftpArray[]['resourceType'] = "File";
}
$resourceName = strrchr($data, " ");
$resourceName = trim($resourceName);
if ($resourceName != ".." && $resourceName != "." && $resourceName != "") {
$ftpArray[]['resourceName'] = $resourceName;
}
}
But the output is this
[0]=>
array(1) {
["resourceType"]=>
string(4) "File"
}
[1]=>
array(1) {
["resourceType"]=>
string(4) "Test"
}
[2]=>
array(1) {
["resourceType"]=>
string(4) "File"
}
[3]=>
array(1) {
["resourceName"]=>
string(9) ".htaccess"
}
Rather than the example I gave at the start of the question. How can I get the array to fill in key values pairs like the first example.
Make an tmp array
foreach ($output as $data) {
$a = array();
if (strpos($data, "d")) {
$a['resourceType'] = "Folder";
} else {
$a['resourceType'] = "File";
}
$resourceName = trim(strrchr($data, " "));
if ($resourceName != ".." && $resourceName != "." && $resourceName != "") {
$a['resourceName'] = $resourceName;
}
$ftpArray[] = $a;
}
Each calling of $ftpArray[] = 'x' adds new item to the array. It does not metter if you add there some second dimension key.
You want to add a datastructure to a array. This, create the datastructure, do your stuff and add it to the array:
foreach ($output as $data) {
$struct = array('resourceType' = > '', 'resourceName' => '');
// do stuff, on the struct
$resourceType = strpos($data, "d");
if ($resourceType) {
$struct['resourceType'] = "Folder";
} else {
$struct['resourceType'] = "File";
}
$resourceName = strrchr($data, " ");
$resourceName = trim($resourceName);
if ($resourceName != ".." && $resourceName != "." && $resourceName != "") {
$struct['resourceName'] = $resourceName;
}
$ftpArray[] = $struct;
}
Notice that there is a sub tile difference with the previous answer, as the structure is always created.
Each [] operation on array adds a new element to the loop, so you would need to create a temporary value and then add it to the loop:
$element = array();
// set the data here
$output_array[] = $element
And second thing with that script string positions start with 0, so if you need to know that character was not found when using strpos you should check the return value with === or !== for FALSE.

Categories