I have 2 arrays. The first array contains the correct word variants and the second array contains incorrect word variants. I want to write them by combining into one as an array, passing in the wrong version of the words to the key and to the value of the correct version of the word. Then write them to a file and use it. I saved the contents of the array in a file, but with a new record to the same file, all the data is cleared and only new entries are re-written and the old entries are deleted automatically. I want that before writing new data to an array, the array is checked for duplication and if such is not written in the file with the array, then let it be written to the file without clearing the previous data of the file. In general, that will select a file or database for storing more than a billion words. Does the database have the best speed or file?
Example first array:
$uncorrect = array
(
0 => "мувосокори",
1 => "мунаггас",
2 => "мангит",
3 => "мангития",
4 => "мунфачир",
5 => "мунфачира",
6 => "манфиатпарасти",
7 => "манфиатчу",
8 => "манфиатчуи",
9 => "манфиатхох",
10 => "манфи",
.....................
);
Example second array:
$correct = array
(
0 => "мувосокорӣ",
1 => "мунағғас",
2 => "манғит",
3 => "манғития",
4 => "мунфаҷир",
5 => "мунфаҷира",
6 => "манфиатпарастӣ",
7 => "манфиатҷӯ",
8 => "манфиатҷӯӣ",
9 => "манфиатхоҳ",
10 => "манфӣ",
.....................
);
I combined two arrays with this code:
$dict = array_combine($uncorrect, $correct);
Example result my array with data here:
$dict = array (
"мувосокори" => "мувосокорӣ",
"мунаггас" => "мунағғас",
"мангит" => "манғит",
"мангития" => "манғития",
"мунфачир" => "мунфаҷир",
"мунфачира" => "мунфаҷира",
"манфиатпарасти" => "манфиатпарастӣ",
"манфиатчу" => "манфиатҷӯ",
"манфиатчуи" => "манфиатҷӯӣ",
"манфиатхох" => "манфиатхоҳ",
"манфи" => "манфӣ",
"минкор" => "минқор",
.....................................
);
I am writing to a file with this code:
file_put_contents("data.json", json_encode($dict));
I will get the array with this code:
$array = json_decode(file_get_contents("data.json"));
You would be better off using a database for this task.
To solve your issue if you decide to keep with the file storage, the reason you are losing old entries is because you forgot to load them before adding new values.
// more or less something like below
$array = json_decode(file_get_contents("data.json"));
$dict = array_combine($incorrect, $correct);
$newArray = array_merge($array, $dict);
file_put_contents("data.json", json_encode($newArray));
This will not be efficient for billions or rows, especially if it's something that gets loaded every time a user loads a page.
Any time you want to add new items just load the file first, then merge the new items in before saving it again. file_put_contents is going to overwrite whatever was there, so you need to get that data before running that function. Something like this:
$array = json_decode(file_get_contents("data.json"));
$newArray = array(
array( "rightWord" => "wrongWord")
);
$finalArray = array_merge($newArray, $array);
file_put_contents("data.json", json_encode($finalArray));
Related
I am writing a page that pulls images and image data out of a multidimensional array. I need to be able to click a button that calls a function to sort out the images by tags(IE tag_GlassDoor & tag_GlassWall) - basically to show only images that do or do not have that particular element (in this case im using 0 and 1 for yes and no), such as a glass door. I can currently make that array display the data, but I cant figure out how to sort the data by one of the array keys, or even really the syntax to pull a single value out at will.
$arrImages[] =
[
'img_sm'=>'image1.jpg',
'tag_GlassDoor'=>0,
'tag_GlassWall'=>1,
];
$arrImages[] =
[
'img_sm'=>'image2.jpg',
'tag_GlassDoor'=>1,
'tag_GlassWall'=>1,
];
Filtering is the answer, it can be used to filter one dimensional Arrays and multidimensional arrays.
the general implementation would be something like this:
$arr = array(
array(
'image' => "data",
'hasObject' => 1
),
array(
'image' => "data",
'hasObject' => 0
),
);
$finteredArray = array_filter($arr, function ($r) {
return (bool) $r['hasObject'];
});
print_r($finteredArray);
// it outputs:
// Array ( [0] => Array ( [image] => data [hasObject] => 1 ) )
This seems like a relatively easy thing to do but I'm struggling a bit. Here is a bit of backstory. I'm currently making a schedule of events based off a web service.
Because of the way it outputs data I've been creating and rearranging the information based off the clients wants/needs.
I've created a time array that basically loops through the open hours in 15 min intervals. Example...
Array
(
[0600] => 0
[0615] => 0
[0630] => 0
[0645] => 0
[0700] => 0
[0715] => 0
[0730] => 0
[0745] => 0
[0800] => 0
[0815] => 0
[0830] => 0
[0845] => 0
[0900] => 0
...etc etc
[2300] => 0
)
Once I've done that I loop(using a foreach) through events and if the time is equal to a key add it to the array. The variables are just items from web service.
$timeArray[date('Hi', $roundStart)] = array(
'e_name' => $eventName,
'e_build_id' => $buildId,
'e_start' => $timeStampS,
'e_end' => $timeStampE,
'e_class' => $eClass,
'e_span' => $fullSpan,
'e_status' => $canCheck,
'e_lanes' => $lanesOpen
);
But I've noticed there is a bug with this and that if you have two events at the same time the last one will override the other one. What I need instead is for the events to be within the same key. So adding two or more arrays to the key.
Let me know if this makes sense?
in your initial array, make the values empty arrays:
Array
(
[0600] => []
...etc etc
[2300] => []
)
then when you assign, just push on the array
$timearray[$time][] = $event;
just make sure you always treat the $timearray indexes as arrays, even if they only contain one (or zero!) events.
good luck!
Just make every entry in your interval array an array
// instead the if condition you can initialize the array in your loop when creating it
if (!is_array($timeArray[date('Hi', $roundStart)])) {
$timeArray[date('Hi', $roundStart)] = array();
}
$timeArray[date('Hi', $roundStart)][] = array(
'e_name' => $eventName,
'e_build_id' => $buildId,
'e_start' => $timeStampS,
'e_end' => $timeStampE,
'e_class' => $eClass,
'e_span' => $fullSpan,
'e_status' => $canCheck,
'e_lanes' => $lanesOpen
);
try this:
Array
(
[0600] => array()
...
and
$timeArray[date('Hi', $roundStart)][] = array(
'e_name' => $eventName,
'e_build_id' => $buildId
...
So instead of setting every hour to 0, better set everything to an empty array in your initial run. Instead of checking against 0, you can then check against an array with 0 length. So basically the same. For your date setting loop, you will now, instead of creating a new array, just push to that array. Something like
array_push($timeArray[date('Hi', $roundStart)], array(
'e_name' => $eventName,
'e_build_id' => $buildId,
'e_start' => $timeStampS,
'e_end' => $timeStampE,
'e_class' => $eClass,
'e_span' => $fullSpan,
'e_status' => $canCheck,
'e_lanes' => $lanesOpen
));
should do the job.
After that, just loop over the dates at any given time and execute them all.
I'm using php with Laravel. I want to update my database with this array, when I excecute this query to update my db, this db updated by 2 times.
It was like array 1, array 1 then array, 2 array 2... What I want just array 1 then array 2. So how do I solve this problem? Thanks.
$chcount = count($kfamily_profile['chname'])-1;
for($x=0;$x<=$chcount;$x++)
{
$childinput[$x] = array(
'child_name' => $kfamily_profile['chname'][$x],
'gender' => $kfamily_profile['chgender'][$x],
'child_pob' => $kfamily_profile['chpob'][$x],
'child_dob' => $kfamily_profile['chdob'][$x]
);
DB::table('kids')
->where('fathers_name','=', $fname)
->where('mothers_name','=', $mname)
->orderBy('child_dob','ASC')
->update($childinput[$x]);
}
I'm working on a PHP script to hold a lot of information.
Lets try to explain our situation!
I have actually 33 different stations.
For each of that 33 stations I have 5 different categories.
And for each of that 33 stations with each 5 different categories i have 37 different values per category.
Do I need an 2d of 3d array for store this information in it ?
Thanks you!
Something like this will work, just add more data as needed:
$station_array =
array(
'station1' => array(
'cat1' => array ('val1','val2','val3'),
'cat2' => array ('val1','val2','val3'),
'cat3' => array ('val1','val2','val3')
),
'station2' => array (
'cat1' => array ('val1','val2','val3'),
'cat2' => array ('val1','val2','val3'),
'cat3' => array ('val1','val2','val3')
),
'station3' => array (
'cat1' => array ('val1','val2','val3'),
'cat2' => array ('val1','val2','val3'),
'cat3' => array ('val1','val2','val3')
)
);
Sounds like a job for a relational database!
But you're correct in your initial assumption. You will need a 3-dimensional array to hold your information because your data has 3 tiers: the stations, the categories, and the values.
A php array will be fine for this
$MyArray = array('Station1' => array('Category1' =>
array('Value1'=> 1000,'Value2'=> 1001),
'Category2' => array('Value1' => 2332)), etc...
'Station2' => array('Category1' =>
array('Value1'=> 1000,'Value2'=> 1001),
'Category2' => array('Value1' => 2332)), etc
etc
);
Once you pass more than two dimensions in an associative array, it's good to start considering using objects to store your information. Objects make it a lot easier to understand how things are organized, they can enforce validation restrictions on your data (make sure it's in the form it should be), and you can call functions on the data to manipulate it (instead of having random external functions manipulating your entire array). An example would be:
class CategoryValue {
var $val; // your value
function __construct($val) {
$this->val = $val;
}
}
class Category {
var $values = array(); // an array of CategoryValue objects
function addValue(CategoryValue $val) {
$this->values[] = $val;
}
}
class Station {
var $categories = array(); // an array of Category objects
function addCategory(Category $category) {
$this->categories[] = $category;
}
}
well, all depends on how you want to acheive, if you dont need to loop through the values, but you just want to store data and alway know whay you want to get, you could use hashes for that, the table would look like:
$data = array(
md5('StationX'.'CategoryY'.'PropertyZ') => 'ValueU',
md5('StationA'.'CategoryB'.'PropertyC') => 'ValueQ'
);
This way you can get the data right away and dont have to bother to check if you initialised CategoryB array for StationA when you want to add value for PropertyZ
php stores associative arrays as hastables technically
... thats all if you really insist on not using databases ;)
I have data contained in an array which is like so,
$file['info']['files'] = array(
[0] => array(
'length' => (int),
'path' => array (
[0] => 'file.txt',
),
),
[1] => array(
'length' => (int),
'path' => array (
[0] => 'directory one',
[1] => 'file2.txt',
),
),
[2] => array(
'length' => (int),
'path' => array (
[0] => 'directory one',
[1] => 'directory two',
[2] => 'file3.txt',
),
),
);
The $file['info']['files'] array can contain any number of elements. The path array contained in each $file['info']['files'] array is where I am having trouble.
It contains information about a file structure. If just 1 element exists then it is a file. If more than one element exists then each element starting from the top is a parent folder of the next element and the last element is the file in the last folder. Taking the example above would be a file structure of
FILE file1.txt
FOLDER directory one
FILE file2.txt
FOLDER directory two
FILE {file3.txt}
I would like to extract this data into my own array structure which is to be as follows,
$sortedFiles = array(
'file1.txt' => (int),
'directory one' => array(
'file2.txt' => (int),
'directory two' => array(
'file3.txt' => (int),
),
),
);
I have this code so far,
foreach($file['info']['files'] as $file) {
// LENGTH AND PATH ARE SET
if(isset($file['length'], $file['path'])) {
// GET COUNT OF FILE PATH ARRAY
$count = count($file['path']);
// SINGLE FILE
if($count == 1) {
$sortedFiles[$file['path'][0]] = $file['length'];
// FILES IN DIRECTORY
} else {
// BUILD ARRAY STRUCTURE FOR DIRECTORIES
}
}
}
I am having trouble when it comes to adding directories to the array. I could do it manually and only go so many directories down each time checking if the array for the directory exists and if not create it, and if it does exist then add to it. I tried this with the code below but it only goes one directory deep (the code went where it says // BUILD ARRAY STRUCTURE above).
// FOLDER NOT SET
if(!isset($files[$file['path'][0]])) {
$sortedFiles[$file['path'][0]] = array($file['path'][1] => $file['length'],);
// FOLDER SET
} else {
$sortedFiles[$file['path'][0]][$file['path'][1]] = $file['length'];
}
How can I dynamically create arrays for each directory that exists and add the information that is needed bearing in mind that the directory structure could be any amount of levels deep?
Thanks for taking the time to read my rather long question and I appreciate any help that anyone gives to me.
You will need to call your function recursively, as in the example below:
function get_contents_dir( $dir )
{
$names = array();
if ( is_dir($dir) && is_readable($dir) )
{
foreach ( scandir($dir) as $file )
{
if ( is_dir($dir."/".$file) && is_readable($dir."/".$file) )
{
$names[] = get_contents_dir($dir."/".$file);
}
if ( is_file($dir."/".$file) && is_readable($dir."/".$file) )
{
$names[] = $dir."/".$file;
}
}
}
return $names;
}
This function first opens the set $dir folder and scans the list of files, adding each found file to the array which is, after scanning the folder, returned as the return value of the function.
The twist comes in when an entry of the scandir() result (list of files and folders in the folder) is actually a folder. If that happens, the function is called from it's internals, recursively (see the line $names[] = get_contents_dir($dir."/".$file); calling the function from within the function) and the subfolder will be indexed too. Rinse and repeat, until all subfolders are indexed.
If you call the function and let it execute, an array will be returned. Each key of the array will be an entry. If it was a file, the value linked to the key is the name of the file, if it was a folder, the value will be another array nested into the previous one.
Here is an example dump taken of the returned array:
array (
0 => './libmysqlclient.so.16.0.0',
1 => './libmysqlclient_r.so.16.0.0',
2 =>
array (
0 => './libs/libboost_thread-mt.a',
1 => './libs/libboost_thread-mt.so.1.38.0',
2 => './libs/libmysql.dll',
3 => './libs/libmysqlclient16_5.1.41-3ubuntu12_i386.deb',
),
3 =>
array (
0 => './radio_sneaker/cl_auto.lua',
1 => './radio_sneaker/sh_auto.lua',
2 => './radio_sneaker/sh_coms.lua',
3 => './radio_sneaker/sh_info.lua',
4 => './radio_sneaker/sv_auto.lua',
5 => './radio_sneaker/sv_hooks.lua',
),
4 => './sv_auto.lua',
)
Compare this output against the tree command ran on the same folder:
| libmysqlclient.so.16.0.0
| libmysqlclient_r.so.16.0.0
| sv_auto.lua
|
+---libs
| libboost_thread-mt.a
| libboost_thread-mt.so.1.38.0
| libmysql.dll
| libmysqlclient16_5.1.41-3ubuntu12_i386.deb
|
\---radio_sneaker
cl_auto.lua
sh_auto.lua
sh_coms.lua
sh_info.lua
sv_auto.lua
sv_hooks.lua
Why don't you use a join function in php to merge the path to check whether it then exists? If it doesn't then go level by level checking if the folder exists and if it doesn't then create in and move further. My point is that creating such a dynamic structure is, first of all, difficult and easy to mess up. Why not to go the easy way?
Imagine that you have an array representing the directory stucture which is initially empty and will be filled in piece by piece. You need to keep track of a "current" item in this array and iterate over the directory names. At each iteration you would create a sub-array under the current item if it does not already exist and then set the current to be this sub-array.
This can be done either with recursion or with iteration, and since it's PHP the "current" marker would need to be a reference.
With this overview in mind, have a look at this question and the answers there. The input there is in the form of a string, but that's just an implode away from your current situation.
I'll let you wrestle this into your code, but heres the important lessons.
turn the flat array into a nested structure
$a = array(
'dir1', 'dir2', 'file.txt'
);
$structure = array(array_pop($a));
foreach (array_reverse($a) as $dir) {
$structure = array($dir => $structure);
}
print_r($structure);
merge one structure into another
$result = array_merge_recursive($result, $structure);
Just iterate over all structures for the merging.