Filtering by PHP - php

I have a $data at a column1 shows me:
"AAA123"
"ABC1234"
"ABD123"
"BAC12"
"CAB123"
"DA125"
and so on..
I would like to show $data starting with only "AB" which shows me at column1 like :
"ABC1234"
"ABD123"
not the others but also other rows and columns related to "ABC1234" and "ABD123"
Thanx in advance.
Sample structure http://img706.imageshack.us/img706/8994/34310422.jpg

If $data is an array of strings, you can use array_filter.
PHP 5.3 or later:
$AB = array_filter($data, function($str) {
return 'AB' == substr($str, 0, 2);
});
before PHP 5.3:
$AB = array_filter($data,
create_function('$str',
'return "AB" == substr($str, 0, 2);'
) );
Or:
function create_prefix_tester($prefix) {
return create_function('$str',
"return '$prefix' == substr(\$str, 0, " . strlen($prefix) . ');'
);
}
$AB = array_filter($data, create_prefix_tester('AB'));
Or you could use a loop:
foreach ($data as $str) {
if ('AB' == substr($str, 0, 2)) {
// do stuff
...
}
}
Edit
From the sample code, it looks like you'll want the loop:
while (FALSE !== ($line = fgets($fp))) {
$row = explode('|', $line); // split() is deprecated
if ('AB' == substr($row[0], 0, 2)) {
switch($sortby) {
case 'schools': // fallthru
default:
$sortValue = $row[0];
break;
case 'dates':
$sortValue = $row[1];
break;
case 'times':
$sortValue = $row[2];
break;
}
array_unshift($row, $sortValue);
$table[] = $row;
}
}
or:
function cmp_schools($a, $b) {
return strcmp($a[0], $b[0]);
}
function cmp_dates($a, $b) {
return $a['datestamp'] - $b['datestamp'];
}
function cmp_times($a, $b) {
return $a['timestamp'] - $b['timestamp'];
}
while (FALSE !== ($line = fgets($fp))) {
$row = explode('|', $line); // split() is deprecated
if ('AB' == substr($row[0], 0, 2)) {
$when = strtotime($row[1] + ' ' + $row[2]);
$row['timestamp'] = $when % (60*60*24);
$row['datestamp'] = $when - $row['timestamp'];
$table[] = $row;
}
}
usort($table, 'cmp_' + $sortby);

I would simply use substr(), as in the following snippet:
if (substr($str, 0, 2) == 'AB') {
// The string is right.
}

Use strpos (http://www.php.net/manual/en/function.strpos.php), like
if (strpos($my_string, "AB") === 0) {
<do stuff>
}
Be very sure to use === instead of ==, because if "AB" is not found then the function will return false, which will equate to 0 using ==.

Related

I want to find my value in an array using just 1 foreach

I have an array lets suppose
$myarr = array(
'1',
'2',
'3',
'4-7',
'9',
'10',
)
$search2 = '2';
$search5 = '5';
I want to check both these 2 variables inside my $myarr. The first one can be easily found by using in_array but the $search5 is there inside '4-7' but what will I do to find the value? I don't want 2 foreach because i know I can use explode and then compare the start and end value. Is there a single or double line function that could help me achieve what I need? Thanks
PHP code demo
<?php
ini_set("display_errors", 1);
$search=2;
$result=null;
$myarr = array(
'1',
'2',
'3',
'4-7',
'9',
'10',
);
echo search_in_array($myarr,$search);
function search_in_array($myarr,$search)
{
$result=false;
array_map(function($number) use ($myarr,$search, &$result){
if(preg_match("/^(\d+)\-(\d+)$/", $number,$matches))
{
if(in_array($search,range($matches[1],$matches[2])))
{
$result= true;
}
}
elseif(preg_match("/^(\d+)$/", $number,$matches))
{
if(in_array($search,$myarr))
{
$result= true;
}
}
}, $myarr);
return $result;
}
Just as another answer:
$myarr = [
'1',
'2',
'3',
'4-7',
'9',
'10',
];
$search2 = '2';
$search5 = '5';
$search12 = '12';
function myInArray($needle, $haystack) {
return in_array(
$needle,
array_reduce(
$haystack,
function($incrementor, $value) {
return array_merge($incrementor, (strpos($value, '-') !== false) ? range(...explode('-', $value)) : [(int)$value]);
},
[]
)
);
}
foreach([$search2, $search5, $search12] as $searchValue) {
echo $searchValue, " is ",(myInArray($searchValue, $myarr) ? '' : 'NOT '), "in the array", PHP_EOL;
}
Probably not as efficient, especially when working with larger ranges of values in $myarr, but a slightly different approach
Demo
Here is almost one-liner,
$search = '5';
$matches = explode('-',array_values(preg_grep('/[-]/', $myarr))[0]);
if(in_array($search, $myarr)|| in_array($search,range($matches[0],$matches[1]))){
echo "found";
}else{
echo "not found";
}
I am exploding by - and then creating range with that and checking that with in_array.
Here is working DEMO
<?php
$myarr = ['1', '2', '3', '4-7', '9', '10'];
$search_array = [2, 5];
$search_results = [];
for ($i = 0; $i < count($search_array); $i++) {
$search_results[$search_array[$i]] = array_search($search_array[$i], $myarr);
if (!$search_results[$search_array[$i]]) {
foreach ($myarr as $value) {
if (strpos($value, "-") !== false) {
$data = explode("-", $value);
if ($search_array[$i] >= $data[0] && $search_array[$i] <= $data[1]) {
$search_results[$search_array[$i]] = array_search($value, $myarr);
}
}
}
}
if (!$search_results[$search_array[$i]]) {
unset($search_results[$search_array[$i]]);
}
}
var_dump($search_results);
Obviously using single foreach i cam up with this code to find ... set of data another is for loop not foreach.
#Ali Zia you can also try this logic like below:
<?php
$myarr = array(
'1',
'2',
'3',
'4-7',
'9',
'10',
);
$flag = 0;
$search = '5';
foreach($myarr as $value){
if($value == $search){
$flag = 1;
break;
}
else if(strpos($value, "-")){
$numberRange = explode("-", $value);
if($numberRange[0] <= $search && $numberRange[1] >= $search){
$flag = 1;
break;
}
}
}
if($flag == 1){
echo "yes number found in the array";
}
else{
echo "sorry not found";
}
Just for the sake of using range() and argument unpacking, because none of the other answers do:
function in_array_range($needle, array $haystack) {
if (in_array((int) $needle, $haystack, true)) {
return true;
}
$haystack = array_map(
function($element) {
return strpos($element, '-')
? range(... explode('-', $element, 2))
: (int) $element;
},
$haystack
);
foreach ($haystack as $element) {
if (is_array($element) && in_array((int) $needle, $element, true)) {
return true;
}
}
return false;
}
The function below returns the index of $needle in $haystack or -1 if no such element has been found.
function find(array $haystack, $needle) {
for ($i = 0; $i < count($haystack); $i++) {
$parts = explode("-", $haystack[$i]);
if (count($parts) == 2) {
if ($needle >= $parts[0] && $needle <= $parts[1]) {
return $i;
}
}
else if ($needle == $parts[0]) {
return $i;
}
}
return -1;
}
The function assumes that $array only contains a single non-negative integer or two non-negative integers separated by a dash.
You can now collect the indices like this:
$indices = array();
foreach ($searchValues as $searchValue) {
$indices[] = find($myarr, $searchValue);
}
Try with following code :
$myarr = array('1','2','3','4-7','9','10');
$search = 1; // Try with 5
$flag1 = false;
foreach($myarr as $number){
if(!is_numeric($number)){
list($start,$end) = explode("-",$number);
if($search >=$start && $search <=$end ){
echo $search .' Found';
}
}else if($flag1 == false){
if(in_array($search,$myarr)){
echo $search .' Found';
$flag1 = true;
}
}
}
Working Demo
I know the answer has already been accepted but here is my approach w/ and w/o using foreach.
(See demo).
With foreach :
<?php
$value = 3;
foreach($myarr as $myval){
list($start, $end) = strpos($myval, '-') ? explode('-', $myval) : [$myval, $myval];
if($value >= $start && $value <= $end){
echo $value . ' found between "' . $start . '" & "' . $end . '" !' . "\n";
}
}
Without foreach, "one line" code :
<?php
$value = 5;
$trueValues = [1,5];
$falseValues = [5, 7, 8];
var_dump(!count(array_diff($trueValues,array_reduce($myarr,function($arr, $item){return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);},[]))));
var_dump(!count(array_diff($falseValues,array_reduce($myarr,function($arr, $item){return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);},[]))));
var_dump(in_array($value, array_reduce($myarr, function($arr, $item){return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);}, array())));
Unfolded :
<?php
var_dump(
!count(
array_diff(
$trueValues,
array_reduce(
$myarr,
function($arr, $item){
return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);
},
[]
)
)
)
);
EDIT : Didn't know the ellipsis operator, thank you #Mark Baker

echoing array from function in php

I am trying to create an array from a function.
The function:
$results = [];
function getDirEnties($directory, &$results) {
$entries = scandir($directory);
foreach ($entries as $item) {
if (!in_array($item, ['.', '..']) && substr($item, 0, 1) !== '.') {
$path = $directory . '/' . $item;
if (is_dir($path)) {
getDirEnties($path, $results);
} else {
$pathInfo = pathinfo($path);
$name = $pathInfo['filename'];
$type = 'unknown';
if (!empty($pathInfo['extension'])) {
$name .= "." . $pathInfo['extension'];
switch (strtolower($pathInfo['extension'])) {
case "gif":
case "jpg":
case "png":
case "jpeg":
case "bmp":
//etc..
$type = 'image';
break;
case "mp4":
$type = 'media';
break;
}
}
$data = [
'name' => $name,
'path' => $pathInfo['dirname'],
'type' => $type,
'time' => filemtime($path)
];
$results[] = $data;
}
}
}
return $results;
}
to populate the function I have the following:
$stmt=$db->prepare('SELECT friend2 as username FROM list_friends
WHERE (friend1 = :username AND friend2 <> :username)
UNION
SELECT friend1 as username FROM list_friends
WHERE (friend2 = :username AND friend1 <> :username)');
$stmt->bindParam(':username', $username);
$stmt->execute();
$friend_rows = $stmt->fetchAll();
foreach ($friend_rows as $rows) {
$friend = strtolower($rows['username']);
$directoryToScan = '/path/to/'.$friend;
$tree = getDirEnties($directoryToScan, $results);
}
I am then trying to echo it out as follows:
function cmp($a, $b) {
$ad = new DateTime($a['time']);
$bd = new DateTime($b['time']);
if ($ad == $bd) {
return 0;
}
return $ad < $bd ? -1 : 1;
}
if ($data !== NULL) {
usort($data, "cmp");
for($i=(count($data)-1)-($feed-1);$i>=(count($data)-10)-($feed-1);$i--){
if($data[$i]['type']=='image'){ echo $data[$i]['name']; }
}
}
I am JUST learning functions and have VERY limited experience with arrays, mostly with mysql arrays so I have no idea how to write this in such a way it returns the $data[] array properly as needed.
You inverted the use of $results and $data
Here you use your $results array as input/output :
$tree = getDirEnties($directoryToScan, $results);
Then later you try to print $data
if ($data !== NULL) {
usort($data, "cmp");
for($i=(count($data)-1)-($feed-1);$i>=(count($data)-10)-($feed-1);$i--){
if($data[$i]['type']=='image'){ echo $data[$i]['name']; }
}
}
But the way you written the code, all your needs are in $results. Use $results !
if ($results !== NULL) {
usort($results, "cmp");
for($i=(count($results)-1)-($feed-1);$i>=(count($results)-10)-($feed-1);$i--){
if($results[$i]['type']=='image'){ echo $results[$i]['name']; }
}
}
If you want to print the entire array, use this. print_r(array_values($ARR));
The answer I marked correct, basically laid out my answer for me although it wasn't "exactly" what I wanted in terms of code. Ultimately all I had to do was change my variables and output a touch.
$tree = getDirEnties($directoryToScan, $results);
to
$tree = getDirEnties($directoryToScan, $data);
then
echo $tree; // I can't believe I missed this
then
return $results;
to
return $data;
Finally because I am sorting times with usort I had to change
'time' => filemtime($path)
to
'time' => date('F d Y h:i A', (filemtime($path)))

String starts with a defined set of words

How to know if a given string starts with a defied set of words?
$allowed = array("foo", "bar");
pseudocode:
$boolean = somefunction($allowed,'food');
$boolean should be TRUE
function doesStringStartWith($string, $startWithOptions)
{
foreach($startWithOptions as $option)
{
if(substr($string, 0, strlen($option)) == $option) // comment this for case-insenstive
// uncomment this for case-insenstive: if(strtolower(substr($string, 0, strlen($option))) == strtolower($option))
{
return true;
}
}
return false;
}
$result = doesStringStartWith('food', array('foo', 'bar'));
function somefunction($allowed, $word) {
$result = array_filter(
$allowed,
function ($value) use ($word) {
return strpos($word, $value) === 0;
}
);
return (boolean) count($result);
}
$boolean = somefunction($allowed,'food');
If you know that all of your prefixes are the same length you could do this:
if ( in_array( substr($input,0,3), $allowed ) {
// your code
}
I came up with the following function:
function testPos($allowed,$s) {
$a = 0;
while($a < count($allowed)) {
if(strpos($s,$allowed[$a]) === 0) {
return true;
}
$a++;
}
}
Now you can try:
$allowed = array('foo','bar');
echo testPos($allowed,'food');

PHP sort array by same value twice

I have array with show names like this:
$shows = array('morning_show_15_02_2014_part2.mp3',
'morning_show_15_02_2014_part1.mp3',
'morning_show_14_02_2014_part2.mp3',
'morning_show_14_02_2014_part1.mp3',
'morning_show_13_02_2014_part2.mp3',
'morning_show_13_02_2014_part1.mp3');
So the list look like:
morning_show_15_02_2014_part2.mp3
morning_show_15_02_2014_part1.mp3
morning_show_14_02_2014_part2.mp3
morning_show_14_02_2014_part1.mp3
morning_show_13_02_2014_part2.mp3
morning_show_13_02_2014_part1.mp3
This is what i get when i loop the directory.
But the list should look like this:
morning_show_15_02_2014_part1.mp3
morning_show_15_02_2014_part2.mp3
morning_show_14_02_2014_part1.mp3
morning_show_14_02_2014_part2.mp3
morning_show_13_02_2014_part1.mp3
morning_show_13_02_2014_part2.mp3
Still ordered by date, but part 1 is first and then comes part 2.
How can i get this list into right order?
Thank you for any help!
Resolved!
Code is prett nasty but i got what i was looking for:
public function getMp3ListAsJSONArray() {
$songs = array();
$mp3s = glob($this->files_path . '/*.mp3');
foreach ($mp3s as $key => $mp3Source) {
$mp3Source = basename($mp3Source);
$mp3Title = substr($mp3Source, 4);
$mp3Title = substr($mp3Title, 0, -4);
$mp3Title = basename($mp3Source, ".mp3");
$mp3Title = str_replace('_', ' ', $mp3Title);
$mp3Title = ucfirst($mp3Title);
$songs[$key]['title'] = $mp3Title;
$songs[$key]['mp3'] = urldecode($this->files_url . '/' . $mp3Source);
}
rsort($songs);
$pairCounter = 1;
$counter = 0;
foreach ($songs as $key => $value) {
$playlist[$pairCounter][] = $value;
$counter = $counter + 1;
if($counter == 2) {
$pairCounter = $pairCounter + 1;
$counter = 0;
}
}
foreach ($playlist as $show) {
$finalList[] = $show[1];
$finalList[] = $show[0];
}
$finalList = json_encode($finalList);
return $finalList;
}
Output is like i described in the topic.
Try to use array sort
Here is an example for you
http://techyline.com/php-sorting-array-with-unique-value/
You must definitely write your own string comparision function. Remember that you have 2 different comparisons. The first compares the first parts for the filenames as strings. The second part compares the numbers, where 20 comes after 2. This is a natural number sorting for the second part. The third part is after the last dot in the filename. This will be ignored.
<?php
function value_compare($a, $b) {
$result = 0;
$descending = TRUE;
$positionA = strpos($a, 'part');
$positionB = strpos($b, 'part');
if ($positionA === $positionB) {
$compareFirstPart = substr_compare($a, $b, 0, $positionA + 1);
if ($compareFirstPart === 0) {
$length = 0;
$offset = $positionA + strlen('part');
$positionDotA = strrpos($a, '.');
$positionDotB = strrpos($b, '.');
$part2A = '';
$part2B = '';
if ($positionDotA !== FALSE) {
$part2A = substr($a, $offset, $positionDotA);
} else {
$part2A = substr($a, $offset);
}
if ($positionDotB !== FALSE) {
$part2B = substr($b, $offset, $positionDotB);
} else {
$part2B = substr($b, $offset);
}
$result = strnatcmp($part2A, $part2B);
} else {
$result = $compareFirstPart;
if ($descending) {
$result = -$result;
}
}
}
return $result;
}
$shows = array('morning_show_15_02_2014_part2.mp3', 'morning_show_15_02_2014_part1.mp3', 'morning_show_14_02_2014_part2.mp3', 'morning_show_14_02_2014_part1.mp3', 'morning_show_13_02_2014_part2.mp3', 'morning_show_13_02_2014_part1.mp3');
usort($shows, 'value_compare');
var_dump($shows);
?>

parse $_SERVER['argv'] into a single array, best method?

I need to parse the $_SERVER['argv'] array into a single array.
I can decide how to get the parameters.
So for example the script was called like this: php script.php name:jack operation:full
I get the parameters in $_SERVER['argv'] like this:
Array
(
[0] => script.php
[1] => name:jack
[2] => operation:full_res
)
How can I easily move those parameters into one array that would be like this:
$param :
Array(['name'] => jack ['operation'] => full_res)
You might be looking for getopt, although it would alter the format of your arguments somewhat.
<?php
var_dump(getopt('',array('name::','operation::')));
?>
From the command line:
$ php opt.php --name=foo --operation=bar
array(2) {
["name"]=>
string(3) "foo"
["operation"]=>
string(3) "bar"
}
A lot of people like my utility function for PHP CLI arguments:
<?php
/**
* parseArgs Command Line Interface (CLI) utility function.
* #usage $args = parseArgs($_SERVER['argv']);
* #author Patrick Fisher <patrick#pwfisher.com>
* #source https://github.com/pwfisher/CommandLine.php
*/
function parseArgs($argv = null) {
$argv = $argv ? $argv : $_SERVER['argv']; array_shift($argv); $o = array();
foreach ($argv as $a) {
if (substr($a, 0, 2) == '--') { $eq = strpos($a, '=');
if ($eq !== false) { $o[substr($a, 2, $eq - 2)] = substr($a, $eq + 1); }
else { $k = substr($a, 2); if (!isset($o[$k])) { $o[$k] = true; } } }
else if (substr($a, 0, 1) == '-') {
if (substr($a, 2, 1) == '=') { $o[substr($a, 1, 1)] = substr($a, 3); }
else { foreach (str_split(substr($a, 1)) as $k) { if (!isset($o[$k])) { $o[$k] = true; } } } }
else { $o[] = $a; } }
return $o;
}
That will do what you ask for and more. See example usage and a helper class at https://github.com/pwfisher/CommandLine.php.
$param = array();
foreach($_SERVER['argv'] as $value) {
if(substr_count($value, ':') !== 1)
continue;
$vals = explode(':', $value);
$param[$vals[0]] = $vals[1];
}
$args = array();
$_args = array_slice($_SERVER['argv'], 1);
foreach ($_args as $_arg) {
$arg = explode(':', $_arg);
if (count($arg) > 1)
$args[ $arg[0] ] = $arg[1];
else
$args[] = $arg[0];
}

Categories