I generate an array with URL's from a webpage with file_get_contents, that i want to remove entry's (key & value) from if they contain specific data.
For example:
[0] = 'http://somesite.com'
[1] = 'http://someothersite.com/article/id/55/file.pdf'
[2] = 'http://someothersite.com/article/id/56/file2.pdf'
[3] = 'javascript:void(0)'
[4] = 'mailto:info#somesite.com'
I want to remove the entry's
http://somesite.com
javascript:void(0)
mailto:info#somesite.com
Because i only need the URL's with the .pdf files.
How do i do that?
You can use array filter for this (note this syntax works for php 5.3+)
$filtered = array_filter($array, function ($a){ return preg_match ('/.pdf$/', $a); });
Hopefully this will help:
$sites[0] = 'http://somesite.com';
$sites[1] = 'http://someothersite.com/article/id/55/file.pdf';
$sites[2] = 'http://someothersite.com/article/id/56/file2.pdf';
$sites[3] = 'javascript:void(0)';
$sites[4] = 'mailto:info#somesite.com';
echo '<pre>'.print_r($sites, true).'</pre>';
//loop through your array of items/sites
foreach($sites as $key=>$value){
//remove whitespace
$value = trim($value);
//get last 4 chars of value
$ext = substr($value, -4, 0);
//check if it is not .pdf
if($ext != '.pdf'){
//unset item from array
unset($sites[$key]);
}
}
echo '<pre>'.print_r($sites, true).'</pre>';
$array = array('http://somesite.com','http://someothersite.com/article/id/55/file.pdf','http://someothersite.com/article/id/56/file2.pdf','javascript:void(0)','mailto:info#somesite.com');
for($i=0; $i<=count($array)+1 ; $i++)
{
if(end(explode('.',$array[$i])) != "pdf" )
{
unset($array[$i]);
}
}
Try this !!!!
$haystack = array (
'0' => 'http://somesite.com',
'1' => 'http://someothersite.com/article/id/55/file.pdf',
'2' => 'http://someothersite.com/article/id/56/file2.pdf',
'3' => 'javascript:void(0)',
'4' => 'mailto:info#somesite.com'
);
$matches = preg_grep ('/pdf/i', $haystack);
//print_r ($matches);
foreach($matches as $k=>$v):
echo $matches[$k]."<br/>";
endforeach;
Documentation
preg_grep
array_filter is always an option, but if you want to remove specific values another good candidate is array_diff:
$remove = [
'http://somesite.com',
'javascript:void(0)',
'mailto:info#somesite.com',
];
$filtered = array_diff($array, $remove);
Related
I want to separate a PHP array when they have a common prefix.
$data = ['status.1', 'status.2', 'status.3',
'country.244', 'country.24', 'country.845',
'pm.4', 'pm.9', 'pm.6'];
I want each of them in separate variables like $status, $countries, $pms which will contain:
$status = [1,2,3];
$country = [244, 24, 845]
$pms = [4,9,6]
My Current code is taking 1.5 seconds to group them:
$statuses = [];
$countries = [];
$pms = [];
$start = microtime(true);
foreach($data as $item){
if(strpos($item, 'status.') !== false){
$statuses[]= substr($item,7);
}
if(strpos($item, 'country.') !== false){
$countries[]= substr($item,8);
}
if(strpos($item, 'pm.') !== false){
$pms[]= substr($item,3);
}
}
$time_elapsed_secs = microtime(true) - $start;
print_r($time_elapsed_secs);
I want to know if is there any faster way to do this
This will give you results for more dynamic prefixs - first explode with the delimiter and then insert by the key to result array.
For separating the value you can use: extract
Consider the following code:
$data = array('status.1','status.2','status.3', 'country.244', 'country.24', 'country.845', 'pm.4','pm.9', 'pm.6');
$res = array();
foreach($data as $elem) {
list($key,$val) = explode(".", $elem, 2);
$res[$key][] = $val;
}
extract($res); // this will separate to var with the prefix name
echo "Status is: " . print_r($status); // will output array of ["1","2","3"]
This snippet took less the 0.001 second...
Thanks #mickmackusa for the simplification
Add continue to each of the if's, so if it's one of them, it won't then run the other ones... not really needed in the last one as obviously the loops starts again anyway. Should save a tiny bit of time, but doubt it'll be as much as you probably want to save.
foreach($data as $item){
if(strpos($item, 'status.') !== false){
$statuses[]= substr($item,7);
continue;
}
if(strpos($item, 'country.') !== false){
$countries[]= substr($item,8);
continue;
}
if(strpos($item, 'pm.') !== false){
$pms[]= substr($item,3);
continue;
}
}
I'd use explode to split them.
something like this:
$arr = array("status" => [],"country" => [],"pm" => []);
foreach($data as $item){
list($key,$val) = explode(".",$item);
$arr[$key][] = $val;
}
extract($res); // taken from david's answer
and it's a much more readable code (in my opinion)
___ EDIT ____
as #DavidWinder commented, this is both not dynamic and will not result in different variables - look at his answer for the most complete solution for your question
Use Explode. Also is a good way to use $limit param for performance and avoiding wrong behavior on having other '.' in values.
$arr = [];
foreach($data as $item){
list($key,$val) = explode('.', $item, 2);
if (!$key || !$val) continue;
$arr[$key][] = $val;
}
var_dump($arr);
If it was me I would do it like so...
<?php
$data = array ('status.1', 'status.2', 'status.3',
'country.244', 'country.24', 'country.845',
'pm.4', 'pm.9', 'pm.6');
$out = array ();
foreach ( $data AS $value )
{
$value = explode ( '.', $value );
$out[$value[0]][] = $value[1];
}
print_r ( $out );
?>
I'm not sure if this'll boost the performance but you could re-arrange your array in a way that each row has a heading and the corresponding value and then use array_column() to group which data you want.
This is an example of how you could group your data in such a way. (PHP 7.1.25+)
$groupedData = array_map(function($arg) {
[$key, $val] = explode('.', $arg); # for PHP 5.6 < 7.1.25 use list($key, $val) = explode(...)
return array($key => $val);
}, $data);
Then, you can pull out all of the country Id's like so:
$countries = array_column($groupedData, 'country');
Here is a live demo.
You can push data into their respective groups while destructuring. The only iterated function call is explode().
Creating individual variables for each group is a design flaw / mismanagement of array data.
Code: (Demo)
$result = [];
foreach ($data as $value) {
[$prefix, $result[$prefix][]] = explode('.', $value, 2);
}
var_export($result);
Output:
array (
'status' =>
array (
0 => '1',
1 => '2',
2 => '3',
),
'country' =>
array (
0 => '244',
1 => '24',
2 => '845',
),
'pm' =>
array (
0 => '4',
1 => '9',
2 => '6',
),
)
Use sscanf() if you want to directly/explicitly cast the numeric values as integers. Demo
I want to separate a PHP array when they have a common prefix.
$data = ['status.1', 'status.2', 'status.3',
'country.244', 'country.24', 'country.845',
'pm.4', 'pm.9', 'pm.6'];
I want each of them in separate variables like $status, $countries, $pms which will contain:
$status = [1,2,3];
$country = [244, 24, 845]
$pms = [4,9,6]
My Current code is taking 1.5 seconds to group them:
$statuses = [];
$countries = [];
$pms = [];
$start = microtime(true);
foreach($data as $item){
if(strpos($item, 'status.') !== false){
$statuses[]= substr($item,7);
}
if(strpos($item, 'country.') !== false){
$countries[]= substr($item,8);
}
if(strpos($item, 'pm.') !== false){
$pms[]= substr($item,3);
}
}
$time_elapsed_secs = microtime(true) - $start;
print_r($time_elapsed_secs);
I want to know if is there any faster way to do this
This will give you results for more dynamic prefixs - first explode with the delimiter and then insert by the key to result array.
For separating the value you can use: extract
Consider the following code:
$data = array('status.1','status.2','status.3', 'country.244', 'country.24', 'country.845', 'pm.4','pm.9', 'pm.6');
$res = array();
foreach($data as $elem) {
list($key,$val) = explode(".", $elem, 2);
$res[$key][] = $val;
}
extract($res); // this will separate to var with the prefix name
echo "Status is: " . print_r($status); // will output array of ["1","2","3"]
This snippet took less the 0.001 second...
Thanks #mickmackusa for the simplification
Add continue to each of the if's, so if it's one of them, it won't then run the other ones... not really needed in the last one as obviously the loops starts again anyway. Should save a tiny bit of time, but doubt it'll be as much as you probably want to save.
foreach($data as $item){
if(strpos($item, 'status.') !== false){
$statuses[]= substr($item,7);
continue;
}
if(strpos($item, 'country.') !== false){
$countries[]= substr($item,8);
continue;
}
if(strpos($item, 'pm.') !== false){
$pms[]= substr($item,3);
continue;
}
}
I'd use explode to split them.
something like this:
$arr = array("status" => [],"country" => [],"pm" => []);
foreach($data as $item){
list($key,$val) = explode(".",$item);
$arr[$key][] = $val;
}
extract($res); // taken from david's answer
and it's a much more readable code (in my opinion)
___ EDIT ____
as #DavidWinder commented, this is both not dynamic and will not result in different variables - look at his answer for the most complete solution for your question
Use Explode. Also is a good way to use $limit param for performance and avoiding wrong behavior on having other '.' in values.
$arr = [];
foreach($data as $item){
list($key,$val) = explode('.', $item, 2);
if (!$key || !$val) continue;
$arr[$key][] = $val;
}
var_dump($arr);
If it was me I would do it like so...
<?php
$data = array ('status.1', 'status.2', 'status.3',
'country.244', 'country.24', 'country.845',
'pm.4', 'pm.9', 'pm.6');
$out = array ();
foreach ( $data AS $value )
{
$value = explode ( '.', $value );
$out[$value[0]][] = $value[1];
}
print_r ( $out );
?>
I'm not sure if this'll boost the performance but you could re-arrange your array in a way that each row has a heading and the corresponding value and then use array_column() to group which data you want.
This is an example of how you could group your data in such a way. (PHP 7.1.25+)
$groupedData = array_map(function($arg) {
[$key, $val] = explode('.', $arg); # for PHP 5.6 < 7.1.25 use list($key, $val) = explode(...)
return array($key => $val);
}, $data);
Then, you can pull out all of the country Id's like so:
$countries = array_column($groupedData, 'country');
Here is a live demo.
You can push data into their respective groups while destructuring. The only iterated function call is explode().
Creating individual variables for each group is a design flaw / mismanagement of array data.
Code: (Demo)
$result = [];
foreach ($data as $value) {
[$prefix, $result[$prefix][]] = explode('.', $value, 2);
}
var_export($result);
Output:
array (
'status' =>
array (
0 => '1',
1 => '2',
2 => '3',
),
'country' =>
array (
0 => '244',
1 => '24',
2 => '845',
),
'pm' =>
array (
0 => '4',
1 => '9',
2 => '6',
),
)
Use sscanf() if you want to directly/explicitly cast the numeric values as integers. Demo
I have an array like below
Array
(
[0] => country-indonesia
[1] => country-myanmar
[2] => access-is_airport
[3] => heritage-is_seagypsy
)
From that array I want to make separate array only for [country] ,[access], [heritage]
So for that I have to check array value by text before '-'. I am not sure how to do it. so i can't apply code here. I just have the array in PHP
A modified answer, if you want to get the specific types only.
<?php
$arr = [
'country-indonesia',
'country-myanmar',
'access-is_airport',
'heritage-is_seagypsy',
];
$new_array = [];
$types = ['country', 'heritage', 'access'];
foreach ($arr as $element) {
$fac = explode('-', $element);
foreach ($types as $type) {
if ($fac[0] === $type) {
$new_array[$type][] = $fac[1];
}
}
}
$country = $new_array['country'];
$access = $new_array['access'];
$heritage = $new_array['heritage'];
var_dump($new_array);
A simple and easy solution in 3 lines of code using array_walk
<?php
$arr = [
'country-indonesia',
'country-myanmar',
'access-is_airport',
'heritage-is_seagypsy',
];
$new_array = [];
array_walk($arr, function($item) use (&$new_array){
//if(false === strpos($item, '-')) return;
list($key,$value) = explode('-', $item, 2);
$new_array[$key][] = $value;
});
print_r($new_array);
Gives this output:
Array
(
[country] => Array
(
[0] => indonesia
[1] => myanmar
)
[access] => Array
(
[0] => is_airport
)
[heritage] => Array
(
[0] => is_seagypsy
)
)
If you don't want empty and duplicate entries:
<?php
$arr = [
'country-indonesia',
'country-myanmar',
'access-is_airport',
'heritage-is_seagypsy',
];
$new_array = [];
array_walk($arr, function($item) use (&$new_array){
if(false === strpos($item, '-')) return;
list($key,$value) = explode('-', $item, 2);
if(empty($value) || array_key_exists($key, $new_array) && in_array($value, $new_array[$key])) return;
$new_array[$key][] = $value;
});
print_r($new_array);
you can do it by using explode and in_array functions
<?php
$arr = ["country-indonesia","country-myanmar","access-is_airport","heritage-is_seagypsy"];
$newArr = array();
foreach($arr as $k=> $val){
$valArr = explode("-", $val);
if(!in_array($valArr[0], $newArr)){
$newArr[] = $valArr[0];
}
}
print_r($newArr);
?>
live demo
You need PHP's strpos() function.
Just loop through every element of the array and try something like:
if( strpos($array[$i], "heritage") != false )
{
// Found heritage, do something with it
}
(Rough example written from my cellphone while feeding baby, may have typos but it's the basics of what you need)
Read further here: http://php.net/manual/en/function.strpos.php
//first lets set a variable equal to our array for ease in working with i.e
// also create a new empty array to hold our filtered values
$countryArray = array();
$accessArray = array();
$heritageArray = array();
$oldArray = Array(country-indonesia, country-myanmar, access-is_airport, heritage-is_seagypsy);
//Next loop through our array i.e
for($x = 0; $x < count($oldArray); $x++){
// now filter through the array contents
$currentValue = $oldArray[$x];
// check whether the current index has any of the strings in it [country] ,[access], [heritage] using the method : strpos()
if(strpos($currentValue,'country')){
//if this particular value contains the keyword push it into our new country array //using the array_push() function.
array_push($countryArray,$currentValue);
}elseif(strpos($currentValue,'access')){
// else check for the access string in our current value
// once it's found the current value will be pushed to the $accessArray
array_push($accessArray,$currentValue);
}elseif(strpos($currentValue,'heritage')){
// check for the last string value i.e access. If found this too should be pushed to //the new heritage array i.e
array_push($heritageArray,$currentValue);
}else{
// do nothing
}
}
//I believe that should work: cheers hope
I have a string with a variable number of key names in brackets, example:
$str = '[key][subkey][otherkey]';
I need to make a multidimensional array that has the same keys represented in the string ($value is just a string value of no importance here):
$arr = [ 'key' => [ 'subkey' => [ 'otherkey' => $value ] ] ];
Or if you prefer this other notation:
$arr['key']['subkey']['otherkey'] = $value;
So ideally I would like to append array keys as I would do with strings, but that is not possible as far as I know. I don't think array_push() can help here. At first I thought I could use a regex to grab the values in square brackets from my string:
preg_match_all( '/\[([^\]]*)\]/', $str, $has_keys, PREG_PATTERN_ORDER );
But I would just have a non associative array without any hierarchy, that is no use to me.
So I came up with something along these lines:
$str = '[key][subkey][otherkey]';
$value = 'my_value';
$arr = [];
preg_match_all( '/\[([^\]]*)\]/', $str, $has_keys, PREG_PATTERN_ORDER );
if ( isset( $has_keys[1] ) ) {
$keys = $has_keys[1];
$k = count( $keys );
if ( $k > 1 ) {
for ( $i=0; $i<$k-1; $i++ ) {
$arr[$keys[$i]] = walk_keys( $keys, $i+1, $value );
}
} else {
$arr[$keys[0]] = $value;
}
$arr = array_slice( $arr, 0, 1 );
}
var_dump($arr);
function walk_keys( $keys, $i, $value ) {
$a = '';
if ( isset( $keys[$i+1] ) ) {
$a[$keys[$i]] = walk_keys( $keys, $i+1, $value );
} else {
$a[$keys[$i]] = $value;
}
return $a;
}
Now, this "works" (also if the string has a different number of 'keys') but to me it looks ugly and overcomplicated. Is there a better way to do this?
I always worry when I see preg_* and such a simple pattern to work with. I would probably go with something like this if you're confident in the format of $str
<?php
// initialize variables
$str = '[key][subkey][otherkey]';
$val = 'my value';
$arr = [];
// Get the keys we want to assign
$keys = explode('][', trim($str, '[]'));
// Get a reference to where we start
$curr = &$arr;
// Loops over keys
foreach($keys as $key) {
// get the reference for this key
$curr = &$curr[$key];
}
// Assign the value to our last reference
$curr = $val;
// visualize the output, so we know its right
var_dump($arr);
I've come up with a simple loop using array_combine():
$in = '[key][subkey][otherkey][subotherkey][foo]';
$value = 'works';
$output = [];
if(preg_match_all('~\[(.*?)\]~s', $in, $m)) { // Check if we got a match
$n_matches = count($m[1]); // Count them
$tmp = $value;
for($i = $n_matches - 1; $i >= 0; $i--) { // Loop through them in reverse order
$tmp = array_combine([$m[1][$i]], [$tmp]); // put $m[1][$i] as key and $tmp as value
}
$output = $tmp;
} else {
echo 'no matches';
}
print_r($output);
The output:
Array
(
[key] => Array
(
[subkey] => Array
(
[otherkey] => Array
(
[subotherkey] => Array
(
[foo] => works
)
)
)
)
)
Online demo
I have following records in text file, need to extract that record form text file and treat them as seperate array variables
r1=(1,2,3)|r2=(4,5,6)|r3=(1,2,3,4,5,7)|rn=(9,6,7,8) seperated by pipe(|)
I need to represent that as array use seperately like below
$r1= Array
(
[0] => 1
[1] => 2
[2] => 3
)
$r2=Array
(
[0] => 4
[1] => 5
[2] => 6
)
I have no idea how to do it, is it possible in php?
Just a plain regular expression to break up the string, followed by an explode on each group:
if (preg_match_all('#(\w+)=\(([\d,]*)\)#', $s, $matches)) {
foreach ($matches[2] as $i => $groups) {
$group_name = $matches[1][$i];
$$group_name = array_map('intval', explode(',', $groups));
}
}
print_r($r1);
print_r($r3);
print_r($rn);
You can use Eval
//Assuming you can pull the content from text file using fread
$temp = "r1=(1,2,3)|r2=(4,5,6)";
$temp=str_replace("=","=array",$temp);
$split=explode("|",$temp);
echo "<pre>";
foreach($split as $k=>$v){
$v="$".$v.";";
//Evaluate a string as PHP code .i.e You will get r1,r2 as a variable now which is array
eval($v);
}
print_r($r1);
print_r($r2);
$data = "r1=(1,2,3)|r2=(4,5,6)|r3=(1,2,3,4,5,7)|rn=(9,6,7,8)";
$arr = explode("|", $data);
$finArray = array();
foreach($arr as $key=>$value)
{
$single = explode('(', $value);
$finArray[] = explode(',', str_replace(')', '', $single[1]));
}
print_r($finArray);
can be done as:
$string="r1=(1,2,3)|r2=(4,5,6)|r3=(1,2,3,4,5,7)|rn=(9,6,7,8)";
$string=str_repla("r1=","",$string);
$yourArray=explode('|', $string);
This code will help you:--
<?php
$file = "/tmp/file1.txt"; // this is your file path
$f = fopen($file, "r");
while ( $line = fgets($f, 1000) ) {
print $line;
$a=explode('|',$line);
print_r($a); // I have explode based on | for you...
foreach($a as $key=>$value)
{
print_r($value);
}
fclose($file);
}
?>
""or""
$a="r1=(1,2,3)|r2=(4,5,6)|r3=(1,2,3,4,5,7)|rn=(9,6,7,8)";
$a=explode('|',$a);
print_r($a);
<?php
$file = "file.txt";
$f = fopen($file, "r");
while ( $line = fgets($f, 1000) ) {
$str = $line;
}
$str1 = explode("|",$str);
foreach($str1 as $temp) {
$str2 = explode("=",$temp);
$data[$str2[0]] = explode(",",trim($str2[1],"()"));
}
echo '<pre>';
print_r($data);
echo '</pre>';
?>
This will do your job.