I am trying to read in a text file which has 21 names like this;
123, bill, bobs
124, joe, public
I have been able to put them into an array but I don't know how to set each name as a variable, as I need to sort them into alphabetical order based on their last name. This is my code so far;
$file = fopen("students.txt", "r");
If ($file) {
while (!feof($file)) {
$array = explode("/n", fread($file, filesize("students.txt")));
print_r($array);
}
} else {
echo 'File unopened';
}
I have tried the following code but it doesnt seem to work;
fscanf ($fp, "%s, %s, %s/n", $num, $first, $last). "<br/>";
Just read the entire file into an array, and explode each line, then usort the results.
$array = file('your_file.txt');
if(false === $array) {
// you had a problem reading file
exit();
}
$exploded_array = array();
foreach($array as $csv) {
$exploded_array[] = explode(',', $csv)
}
usort($exploded_array, function ($a, $b) {
if ($a[2] == $b[2]) {
return 0;
}
return ($a[2] < $b[2]) ? -1 : 1;
}
You can also look at using fgetscv() instead of the combination of file() and explode(). Either way it is pretty much the same.
Your file related code is overcomplicated.
$users = file('students.txt', FILE_SKIP_EMPTY_LINES);
array_walk($users, function (&$val) {
$newAr = explode(',', $val);
$val = array_map('trim', $newAr);
});
usort($users, function($a, $b) {
return strnatcmp($a[2], $b[2]);
});
var_dump($users);
Example with fake data #3v4l
Alternativly you may use fgetcsv to get the values from the file as #MarkB pointed out in the comments of your question
Related
i have dates and names in text form in file like
2-4-2020,bat
14-3-2020,ball
25-6-2019,purse
27-8-2019,rice
so i m trying to sort it in ascending order
<?php
$newdates=$mydates=array();
$lines = file('n:/mydata.txt');
foreach($lines as $data)
{
$mydates[]=explode(',',$data);
}
$countdates=count($mydates);
for ($i=0;$i<$countdates;$i++){
$chkdate=$mydates[$i][0];
$currentdate=DateTime::createFromFormat('d-m-Y', $chkdate)->format('d-m-Y');
$mydates[$i][0]=$currentdate;
}
array_multisort($mydates);
$newdates=$mydates;
$file = fopen("n:/newdates.txt","w");
foreach ($newdates as $contentline)
{
fputcsv($file,$contentline);
}
fclose($file);
but its not sorting at all
It might be done a little simpler. You need to use usort() and strtotime() functions.
Here is simplified example
$mydates= array(
['2-4-2020','bat'],
['14-3-2020','ball'],
['25-6-2019','purse'],
['27-8-2019','rice']
);
usort($mydates, function($a,$b) {
return strtotime($a[0]) > strtotime($b[0]);
});
foreach ($mydates as $contentline) {
echo json_encode($contentline);
}
You can read the file into an array using the file function. Then you can sort the array using usort:
$fileName = 'n:/mydata.txt';
$lines = file($fileName);
usort($lines, function($a, $b) {
foreach (['a', 'b'] as $variable) {
$parts = explode(',', $$variable);
$$variable = DateTime::createFromFormat('j-n-Y', $parts[0]);
}
return $a < $b ? -1 : 1;
});
file_put_contents(implode("\n", $lines), $fileName);
So I have two arrays:
$badwords = array('bad-word', 'some-racist-term', 'nasty', 'bad-language');
$inputphrases = array('this-is-sentence-with-bad-word', 'nothing-bad-here', 'more-clean-stuff', 'this-is-nasty', 'this-contains-some-racist-term', 'one-more-clean', 'clean-clean', 'contains-bad-language');
I need to compare elements of input phrases array with bad words array and output new array with phrases WITHOUT bad words like this:
$outputarray = array('nothing-bad-here', 'more-clean-stuff','one-more-clean', 'clean-clean');
I tried doing this with two foreach loops but it gives me opposite result, aka it outputs phrases WITH bad words.
Here is code I tried that outputs opposite result:
function letsCompare($inputphrases, $badwords)
{
foreach ($inputphrases as $inputphrase) {
foreach ($badwords as $badword) {
if (strpos(strtolower(str_replace('-', '', $inputphrase)), strtolower(str_replace('-', '', $badword))) !== false) {
$result[] = ($inputphrase);
}
}
}
return $result;
}
$result = letsCompare($inputphrases, $badwords);
print_r($result);
this is not a clean solution, but hope, you'll got what is going on. do not hesitate to ask for clearence. repl.it link
$inputphrases = array('this-is-sentence-with-bad-word', 'nothing-bad-here', 'more-clean-stuff', 'this-is-nasty', 'this-contains-some-racist-term', 'one-more-clean', 'clean-clean', 'contains-bad-language');
$new_arr = array_filter($inputphrases, function($phrase) {
$badwords = array('bad-word', 'some-racist-term', 'nasty', 'bad-language');
$c = count($badwords);
for($i=0; $i<$c; $i++) {
if(strpos($phrase, $badwords[$i]) !== false){
return false;
}
}
return true;
});
print_r($new_arr);
Can anyone please advise whether I can write a function for usort that will do the following in PHP :
Firstly I have a bunch of directories that all have two files inside - these two files each contain a number as plain text
Here is what I want to do :
glob the list of directories into an array call $dirs
use a usort function to do the following :
Read the two files (file1.txt and file2.txt) in each directory and multiply them together to create a 3rd number called $value
Sort the original $dirs array into descending order by the $value for each dir.
Ok - I can glob the files like this:
$dirs = glob('*',GLOB_NOSORT|GLOB_ONLYDIR);
and I can pull the values easily enough using file_get_contents but I can't figure out how to combine all of this into a function for usort.
Try this:
<?php
$dirs = array();
foreach (glob('*',GLOB_NOSORT|GLOB_ONLYDIR) as $dir) {
$value =
(int)file_get_contents($dir.'/file1.txt') *
(int)file_get_contents($dir.'/file2.txt') ;
$dirs[] = array(
'path' => $dir,
'value' => $value,
);
}
usort($dirs, function($a, $b) {
return $b['value'] - $a['value'];
});
Then you want to get one-dimensional result,
$dirs = array_map(function ($dir) {
return $dir['path'];
}, $dirs);
The following snippet will do the trick:
$dirs = glob('*',GLOB_NOSORT|GLOB_ONLYDIR);
usort($dirs, function ($a, $b) {
$val_a = $val_b = 1;
foreach(scandir($a) as $file) {
if(strpos($file, '.') === 0) {
continue;
}
$val_a *= intval(trim(file_get_contents($a. '/' . $file)));
}
foreach(scandir($b) as $file) {
if(strpos($file, '.') === 0) {
continue;
}
$val_b *= intval(trim(file_get_contents($b. '/' . $file)));
}
if($val_a === $val_b) {
return 0;
} else if($val_a > $val_b) {
return 1;
} else {
return -1;
}
});
var_dump($dirs);
Assuming you're using 5.3.0 or better, you can use an anonymous function to do this. Below you will see the function buildSort, which returns a function object (called by PHP a "closure", although it's heavily debated in some circles whether this term is being correctly applied.) We'll use this to "memoize" the reads of dir/file1.txt and dir/file2.txt, as well as the math operations, so we only need to perform those once per directory:
<?php
function buildSort(&$values) {
return function ($a, $b) use(&$values) {
if (!isset($values[$a])) {
$values[$a] = file_get_contents($a.'/file1.txt')*
file_get_contents($a.'/file2.txt');
}
if (!isset($values[$b])) {
$values[$b] = file_get_contents($b.'/file1.txt')*
file_get_contents($b.'/file2.txt');
}
return strcmp($values[$a], $values[$b]);
};
}
$dirs = glob('*',GLOB_NOSORT|GLOB_ONLYDIR);
$values = array();
$sort = buildSort($values);
usort($dirs, $sort);
var_dump($dirs);
The answer that avoids passing $values by reference is left as an exercise for the reader. :)
I have following url:
www.example.com/index.php/search/search_data/Doctor:a/Gender:Male/Language:Urdu/
and I want to convert it to associative array like
$data=array(
'Doctor'=> 'a',
'Gender'=> 'Male',
'Language'=> 'Urdu'
);
I have tried to do this using codeIgniter's URI class function
$this->uri->uri_to_assoc(n)
but as it accepts the data to be separated via '/' but I am having data with ':' as separator.
please help me.
I don't think there's an easier way to do this, rather than to do it manually.
First, retrieve the total segments, loop through, see if it contains ":", then add it into the array.
$segments = $this->uri->segment_array();
$search_array = array();
foreach($segments as $segment) {
if (strpos($segment, ":") !== FALSE) {
$e_array = explode(":", $segment);
$search_array[$e_array[0]] = $e_array[1];
}
}
Running that snippet somewhere will give you desirable results, $search_array will be an associative array with key => value.
You could hack the URI.php file. Change lines 431 - 439 to;
if (strpos($seg, ":") !== FALSE) {
list($parameter, $value) = explode(':', $seg);
if ($i % 2) {
$retval[$parameter] = $value;
} else {
$retval[$parameter] = $value;
$lastval = $seg;
}
} else {
if ($i % 2) {
$retval[$lastval] = $seg;
} else {
$retval[$seg] = FALSE;
$lastval = $seg;
}
}
How to send an indexes name for php array vairable.
the array is
$array = array('Somthing'=>array('More'=>array('id'=> 34)));
and now I want to display this thing but with a variable name I don't know how to explain so I write what I want to have.
$index_name = '[Something][More][id]';
$array{$index_name};
Is it possible in any way ?
Not in one go like that. Here's how you'd do it:
$array['Something']['More']['id']
If you particularly wanted access multidimensional arrays with a single string, then you could build a function to do that:
function array_multi(Array $arr, $path) {
$parts = explode(".", $path);
$curr =& $arr;
for ($i = 0, $l = count($parts); $i < $l; ++$i) {
if (!isset($curr[$parts[$i]])) {
// path doesn't exist
return null;
} else if (($i < $l - 1) && !is_array($curr[$parts[$i]]) {
// path doesn't exist
return null;
}
$curr =& $curr[$parts[$i]];
}
return $curr;
}
// usage:
echo array_multi($array, "Something.More.id"); // 34
echo array_multi($array, "Something.More"); // array("id" => 34)
Recursive version supporting your syntax with square brackets:
$array = array('Something'=>array('More'=>array('id'=> 34)));
$string = '[Something][More][id]';
echo scan_array($string, $array);
function scan_array($string, $array) {
list($key, $rest) = preg_split('/[[\]]/', $string, 2, PREG_SPLIT_NO_EMPTY);
if ( $key && $rest ) {
return scan_array($rest, $array[$key]);
} elseif ( $key ) {
return $array[$key];
} else {
return FALSE;
}
}
Ok, I know this is how people get shot. But c'mon, eval() is not always the wrong answer.
$array = array('Something'=>array('More'=>array('id'=> 34)));
$index_name = '[Something][More][id]';
eval('$val = $array'.$index_name.';'); // Wrap in a function or something
You could do this with eval():
<?php
$array = array('Somthing'=>array('More'=>array('id'=> 34)));
$index_name = "['Somthing']['More']['id']";
$stmt='echo $array'.$index_name.';';
eval($stmt);
?>
UPDATE:
It seems some SO users are uncomfortable with the idea of using eval(). I think it makes sense to read this thread which discusses the pros and cons before deciding whether to use this in your own code.
If you've cornered yourself into needing to do something like this, there's a pretty good chance you've done something else in a poor way. There's valid reasons to do this, but not very often.
function key_path($arr, $keys) {
return $keys ? key_path($arr[array_shift($keys)], $keys) : $arr;
}
$arr['Something']['More']['id'] = 34;
$keys = array('Something', 'More', 'id');
var_dump( key_path($arr, $keys));