Hope someone can point me in the right direction here...
I've got directory paths and partial file outputs form a unix grep. I have a flat array from these outputs. Now I'd like to do a bit of PHP magic to turn this flat array into a more hierarchical multidimensional array for more refined user output
Current array;
array(7) {
[0]=>
string(160) "/home/user/data/section1/dir1/20120107/filename.txt:random text after the colon"
[1]=>
string(160) "/home/user/data/section1/dir1/20120108/filename.txt: More random text after the colon"
[2]=>
string(160) "/home/user/data/section1/dir2/20120107/filename.txt: More random text after the colon"
[3]=>
string(160) "/home/user/data/section1/dir2/20120108/filename.txt: More random text after the colon"
[4]=>
string(160) "/home/user/data/section1/dir3/20120107/filename.txt: More random text after the colon"
[5]=>
string(160) "/home/user/data/section1/dir3/20120106/filename.txt: More random text after the colon"
[6]=>
string(160) "/home/user/data/section1/dir3/20120108/filename.txt: More random text after the colon"
}
What i would really like
array(1) {
array(3) {
["dir"]=>
string(4) "dir1"
["date"]=>
string(8) "20120107"
["text"]=>
array (2) {
[0]=>
string(160) "random text after the colon"
[1]=>
string(160) "More random text after the colon"
}
}
array(3) {
["dir"]=>
string(4) "dir1"
["date"]=>
string(8) "20120108"
["text"]=>
array (2) {
[0]=>
string(160) "More random text after the colon"
[1]=>
string(160) "More random text after the colon"
}
}
array(3) {
["dir"]=>
string(4) "dir2"
["date"]=>
string(8) "20120107"
["text"]=>
array (2) {
[0]=>
string(160) "More random text after the colon"
[1]=>
string(160) "More random text after the colon"
}
}
}
I have tried a lot of foreach's, SPL iterator methods, but i'm just not coming out trumps. Looking for any guidance.
Thanks all
This code (using a for loop):
<?php
$data[] = "/home/user/data/section1/dir1/20120107/filename.txt:random text after the colon";
$data[] = "/home/user/data/section1/dir1/20120108/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir2/20120107/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir2/20120108/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120107/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120106/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120108/filename.txt: More random text after the colon";
for($i = 0; $i < count($data); $i++) {
$data[$i] = str_replace('/home/user/data/section1/','',$data[$i]);
$tmp = explode('/', $data[$i]);
$newData[$i] = array(
'dir' => $tmp[0],
'date' => $tmp[1]
);
$tmp = explode(':', $tmp[2]);
$newData[$i]['fileName'] = $tmp[0];
$newData[$i]['text'] = $tmp[1];
}
print_r($newData);
?>
Or this code (using a foreach loop):
<?php
$data[] = "/home/user/data/section1/dir1/20120107/filename.txt:random text after the colon";
$data[] = "/home/user/data/section1/dir1/20120108/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir2/20120107/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir2/20120108/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120107/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120106/filename.txt: More random text after the colon";
$data[] = "/home/user/data/section1/dir3/20120108/filename.txt: More random text after the colon";
foreach($data as $d) {
$tmp = explode('/', str_replace('/home/user/data/section1/','',$d));
$tmp2 = explode(':', $tmp[2]);
$newData[] = array(
'dir' => $tmp[0],
'date' => $tmp[1],
'filename' => $tmp2[0],
'text' => $tmp2[1]
);
}
print_r($newData);
?>
Outputs:
Array
(
[0] => Array
(
[dir] => dir1
[date] => 20120107
[fileName] => filename.txt
[text] => random text after the colon
)
[1] => Array
(
[dir] => dir1
[date] => 20120108
[fileName] => filename.txt
[text] => More random text after the colon
)
============ more data here ============
[6] => Array
(
[dir] => dir3
[date] => 20120108
[fileName] => filename.txt
[text] => More random text after the colon
)
)
Explode each string of path with "/".You will get an array after that.Then push required element in the array.
Make a foreach over the first array and preg_match() the elements for the informations you want to extract from each string.
foreach( $firstArray => $strElement )
{
$newArray[] = array();
if( preg_match( "~(?<=section1/)[.-\w]*~i", $strElement, $astrMatches) >= 1 )
$newArray['dir'] = $astrMatches[0];
...etc...
}
function magic($array_of_strings)
{
define('REGEX','_^/home/user/data/section1/(dir\d+)/(\d+)/filename.txt:(.*)$_');
$ret_array = array();
foreach($array_of_strings as $string) {
if (preg_match(REGEX, $string, $matches)) {
$ret_array []= array(
'dir'=>$matches[1],
'date'=>$matches[2],
'text'=>$matches[3],
);
}
}
return $ret_array;
}
Ok this will do the job, you can change the directory structure as much as you like as long as the the last two directories keep the same order /dir/date.
You can add as many strings as you like to the text section of the array by seperating them with multiple colons after the URL. e.g. /blah/dir/date/filename.txt : string 1 : string 2.
Your original array must be called $array.
Enjoy:
foreach ($array as $string) {
$temp = array();
$temp["strings"] = explode(':', $string); //Convert the string into an array using `:` as a seperator
$temp["path"] = explode('/', $temp["strings"][0]); //Convert the url into an array using `/` as a seperator (each directory is it's own entry)
$path_count = count($temp["path"]); //Count number of directories in the url
$output = array(
"dir" => $temp["path"][$path_count - 3],
"date" => $temp["path"][$path_count - 2],
"text" => array()
);
foreach ($temp["strings"] as $index => $value) { //Loop through and add any additional text to array
if ($index) {
array_push($output["text"], trim($value));
}
}
print_r($output);
}
Thanks all for the input and scripts. I have actually learned quite a bit about massaging data into multidimensional arrays from these scripts. Unfortunately, none of them worked out exactly as i wanted. One thing i've learned researching this issue, is, 'is there another way to present the data?' and in this case i found it. A shell script, to search all files, output the filename, and then the relevant text.
find /home/user/data/section1 -name 'filename.txt' | xargs grep -il texttxet |
while read file
do
echo "$file"
grep -i -A 4 texttxet "$file"
done
File:/home/user/data/section1/dir1/20120107/filename.txt
line1
line2
line3
File:/home/user/data/section1/dir1/20120108/filename.txt
line1
line2
File:/home/user/data/section1/dir2/20120108/filename.txt
line1
line2
I can easily get this info in an array from this point. Thanks all again
Related
I have an array that looks like this:
Array
(
[basisprijs] => 17,00
[basisstaffel] =>
3-10:17;
10-20:14;
20-30:12;
30-40:10;
40-50:7,50;
50-60:6,50;
60-110:6;
[minimaalformaat] => 10x3
[maximaalformaat] => 120x5000
[breedte] => 12
[hoogte] => 4
[aantal] => 1
[Lijmlaag] => Wit(prijsberekening)+($m2*4);
)
I want to create a new array from [basisstaffel] with after each ; a new line starting, so the desired end result would be:
Array
(
[0] = > 3-10:17;
[1] = > 10-20:14;
[2] = > 20-30:12;
[3] = > 30-40:10;
[4] = > 40-50:7,50;
[5] = > 50-60:6,50;
[6] = > 60-110:6;
)
How can I do that? Using explode on the ; makes me lose that part of the value. So is there another way?
The first array is called $productarray
You could just use the explode function and after that, do a foreach loop and add the ';' symbol again, like so:
$newArray=array();
$myArray=array();
$myArray['basisprijs'] = '17,00';
$myArray['basisstaffel'] ='3-10:17;10-20:14;20-30:12;30-40:10;40-50:7,50;50-60:6,50;60-110:6';
$myArray['minimaalformaat'] = '10x3';
$myArray['maximaalformaat'] = '120x5000';
$myArray['breedte'] = '12';
$myArray['hoogte'] = '4';
$myArray['aantal'] = '1';
$myArray['Lijmlaag'] = 'Wit(prijsberekening)+($m2*4)';
$basisstafel=$myArray['basisstaffel'];
$tmp = explode(";", $basisstafel);
foreach ($tmp as $ind){
$newArray[]=$ind.';';
}
echo "<pre>";
print_r($newArray);
echo "</pre>";
You can use preg_split and use the PREG_SPLIT_DELIM_CAPTURE flag.
This will return matches array with delimiter = 0, match = 1
https://www.php.net/manual/en/function.preg-split.php
PREG_SPLIT_DELIM_CAPTURE
If this flag is set, parenthesized expression in the delimiter pattern will be captured and returned as well.
<?php
$productArray = [
'basisprijs' => '17,00',
'basisstaffel' =>'
3-10:17;
10-20:14;
20-30:12;
30-40:10;
40-50:7,50;
50-60:6,50;
60-110:6;',
'minimaalformaat' => '10x3',
'maximaalformaat' => '120x5000',
'breedte' => 12,
'hoogte' => 4,
'aantal' => 1,
'Lijmlaag' => 'Wit(prijsberekening)+($m2*4);'
];
$basisstaffel = explode(";", rtrim($productArray['basisstaffel'], ';'));
var_dump($basisstaffel);
Result : array(8) { [0]=> string(14) " 3-10:17" [1]=> string(14) " 10-20:14" [2]=> string(14) " 20-30:12" [3]=> string(14) " 30-40:10" [4]=> string(16) " 40-50:7,50" [5]=> string(16) " 50-60:6,50" [6]=> string(14) " 60-110:6" }
?>
It looks like you have newlines after ; so you can preg_split by whitespace:
$result = preg_split('/\s+/', $input['basisstaffel']);
To avoid first empty item add PREG_SPLIT_NO_EMPTY flag:
$result = preg_split('/\s+/', $input['basisstaffel'], -1, PREG_SPLIT_NO_EMPTY);
Or simply use explode with \n or \r\n\ (you must know type of newlines you have):
$result = explode("\n", $input['basisstaffel']);
I have a long string that is constructed like this:
randomstring number randomstring number randomstring number
I need to group these random strings and numbers together so that I get an array like this:
array = [[randomstring, number], [[randomstring, number], [randomstring, number]]
I don't know the amount of spaces between the strings and numbers. Any suggestions?
UPDATE
Since Edwin Moller's answer I'm now left with this array:
Array (46) {
[0] =>
array(2) {
[0]=>
string(20) "string"
[1]=>
string(7) "number"
}
[1]=>
array(2) {
[0]=>
string(5) ""
[1]=>
string(7) ""
}
[2] =>
array(2) {
[0]=>
string(10) ""
[1]=>
string(11) ""
}
[3] =>
array(2) {
[0]=>
string(10) ""
[1]=>
string(11) ""
}
[4] =>
array(2) {
[0]=>
string(10) ""
[1]=>
string(11) ""
}
The array elements that have 2 empty elements themselves need to be removed.
I'll leave it with this solution. It's not elegant at all, but I don't know what these 'empty' strings are. It doesn't respond to whitespace, space, any character test so I used the strlen() function:
$str = preg_replace('!\s+!', ' ', $longstring);
$parts = explode(" ", $str);
$nr = count($parts);
for ($i = 0; $i < $nr; $i = $i + 2) {
if(strlen($parts[$i]) > 20) { // ugly, but it works for now..
$tmp[] = [$parts[$i], $parts[$i + 1]];
}
}
// unsetting these elements because they are longer than 30
unset($tmp[0]);
unset($tmp[1]);
unset($tmp[2]);
$longstring = "randomstring1 1001 randomstring2 205 randomstring3 58";
// First, take care of the multiple spaces.
$str = preg_replace('/\s+/', ' ', $longstring);
// split in parts on space
$parts = explode(" ",$str);
$nr = count($parts);
$tmp = array();
for ($i=0; $i<$nr; $i=$i+2){
$tmp[] = array($parts[$i], $parts[$i+1]);
}
echo "<pre>";
print_r($tmp);
echo "</pre>";
You might want to make sure it is an even number. (check $nr).
Edit: OP says you have some empty elements in the array $parts.
I don't know what causes that, possibly some encoding issues, not sure without having the original material (string).
A wild guess: Try to utf8_decode the original string, then do the preg_replace, and then print_r.
Like this:
$longstring = "randomstring1 1001 randomstring2 205 randomstring3 58";
$longstring = utf8_decode($longstring);
$str = preg_replace('/\s+/', ' ', $longstring);
$parts = explode(" ",$str);
echo "<pre>";
print_r($parts);
echo "</pre>";
explode string and then check it like this
Online Demo
$str="randomstring number randomstring number randomstring number";
$exp=explode(" ",$str);
for($i=0;$i<count($exp);$i++)
{
if(trim($exp[$i])=="")
continue;
$result[]=array(0=>$exp[$i],1=>$exp[$i+1]);
$i++;
}
var_dump($result);
Try the following
//Our string
$string = "randomstring 11 randomstring 22 randomstring 33";
//Split them up if they have MORE THAN ONE space
$firstSplit = preg_split('/\s\s+/', $string);
//Set up a new array to contain them
$newArray = array();
//For each of the ones like "randomstring 11"
foreach($firstSplit as $key => $split){
//Split them if they have ONE OR MORE space
$secondSplit = preg_split('/\s+/', $split);
//Add them to the array
//Note: change this part to structure the array however you'd like
$newArray[$key]["string"] = $secondSplit[0];
$newArray[$key]["integer"] = $secondSplit[1];
}
The comments should explain well enough what is happening here, it will leave you with the following:
array (size=3)
0 =>
array (size=2)
'string' => string 'randomstring' (length=12)
'integer' => string '11' (length=2)
1 =>
array (size=2)
'string' => string 'randomstring' (length=12)
'integer' => string '22' (length=2)
2 =>
array (size=2)
'string' => string 'randomstring' (length=12)
'integer' => string '33' (length=2)
I do not know if it is the shortest way but i would say your issue can be consist of this steps
1- convert the multi spaces to one space
2- explode the big string to one array has all the sub string
3- group the elements by loop over the big array
<?php
$str = 'randomstring1 number1 randomstring2 number2 randomstring3 number3';
//remove the spaces and put all the element in one array
$arr = explode(' ', $str);
$space = array('');
$arr = array_values(array_diff($arr, $space));
//now loop over the array and group elements
$result = $temArr = array();
foreach($arr as $index => $element){
if($index % 2){//second element (number)
$temArr[] = $element;
$result[] = $temArr;
$temArr = array();
}else{//first element (randomstring)
$temArr[] = $element;
}
}
//print the result
var_dump($result);die;
?>
First split by 2 or more spaces, then split those groups by the single space.
Try this:
$input = 'randomstring1 number1 randomstring2 number2 randomstring3 number3';
$groups = preg_split("/[\s]{2,}/", $input );
$result = array_map(function($i){
return explode(' ', $i);
}, $groups);
Which gets me this result:
array(3) {
[0] = array(2) {
[0] = string(13) "randomstring1"
[1] = string(7) "number1"
}
[1] = array(2) {
[0] = string(13) "randomstring2"
[1] = string(7) "number2"
}
[2] = array(2) {
[0] = string(13) "randomstring3"
[1] = string(7) "number3"
}
}
I have a Php array that have values of times as array values and timestamps as key array is like this:
array(
144454884=>"12:00am", 145454884=>"12:30am", 144474884=>"1:00am", 144454864=>"1:30am", 143354884=>"1:00am", 144654884=>"1:30am", 1444567584=>"2:00am "
);
Timestamp values in above example are not real I wrote an example they are useless anyway unless your timezone matches mine.
Problem:
I need to get "1:00am" and "1:30am" twice I can get repeating values 1 time as shown in answer here:
php return only duplicated entries from an array
I need both repeating values two times with both keys and values being repeated because I need to eliminate those timestamps from week time on my system because of daylight saving a time is repeating and I don't want to show 1:00am at all I just want to show this time as unavailable.
I am not 100% sure what you wanted but this is what I think you need.
Assuming your input array is called $a
$b = array_flip(array_flip($a));
$c = array_diff_key($a, $b);
$b will contain an array of unique values.
$c will contain the elements that were removed.
Results of $b and $c are as follows:
array(5) {
[144454884] = string(7) "12:00am"
[145454884] = string(7) "12:30am"
[143354884] = string(6) "1:00am"
[144654884] = string(6) "1:30am"
[1444567584] = string(7) "2:00am "
}
array(2) {
[144474884] = string(6) "1:00am"
[144454864] = string(6) "1:30am"
}
This code works :
<?php
$array_new = [];
$array_tmp = [];
$array = array(1=>'1233',2=>'12334',3 =>'Hello' ,4=>'hello', 5=>'U');
//loop trough all elements in array and for ever element create key
//For "world" key is "world"
//For "World" key is "world"
//For "WORLD" key is "world"
//So all this cases have same key and differenet representation eg. "world" => ["world","World","WORLD"]
foreach($array as $k => $v){
$index = strtolower($v);
$array_tmp[$index][] = $v;
}
//loop trough new array with new keys and if there are more than one element(> 1) for some key, all of his representations put in new array
foreach($array_tmp as $k => $v){
if(count($v) > 1){
foreach($v as $k2 => $v2){
$array_new[] = $v2;
}
}
}
echo '<pre>';
print_r($array_new);
echo '<pre>';
A possible solution keeping the key information (I will assign the intermediate results to their own variables otherwise it can be confusing to read)
$array = array(
143354883 => "1:00am",
144454884 => "12:00am",
145454884 => "12:30am",
144474884 => "1:00am",
144454864 => "1:30am",
143354884 => "1:00am",
144654884 => "1:30am",
1444567584 => "2:00am ",
0 => 4,
1 => 4,
2 => 4,
3 => "Test",
4 => "TEST",
5 => "test "
);
// Used this array_iunique function: http://stackoverflow.com/questions/2276349/case-insensitive-array-unique
function array_iunique($array) {
return array_intersect_key(
$array,
array_unique(array_map("StrToLower",$array))
);
}
$unique = array_iunique($array);
// Then get the difference by key, that will give you all the duplicate values:
$diff_key = array_diff_key($array, $unique);
// Now we have to find the values that are in the $diff_key and the $unique because we also want to have those:
$correspondingValues = array_uintersect($unique, $diff_key, "strcasecmp");
// Then we have to combine the $duplicate values with the $diff_key and preserve the keys:
$result = array_replace($correspondingValues, $diff_key);
var_dump($result);
Will result in:
array(10) {
[143354883]=>
string(6) "1:00am"
[144454864]=>
string(6) "1:30am"
[0]=>
int(4)
[3]=>
string(4) "Test"
[144474884]=>
string(6) "1:00am"
[143354884]=>
string(6) "1:00am"
[144654884]=>
string(6) "1:30am"
[1]=>
int(4)
[2]=>
int(4)
[4]=>
string(4) "TEST"
}
I have an array that I'm creating inside my PHP script, the var_dump function gives me this value :var_dump($arrayOfValues);
array(3) {
[0]=> array(2) {
[0]=> string(12) "BusinessName"
[1]=> string(13) "ITCompany"
}
[1]=> array(2) {
[0]=> string(7) "Address"
[1]=> string(58) "29 xxxxxx,Canada"
}
[2]=> array(2) {
[0]=> string(20) "PrimaryBusinessPhone"
[1]=> string(14) "(444) 111-1111"
}
[3]=> array(2) {
[0]=> string(13) "BusinessEmail"
[1]=> string(24) "xx#example.com"
}
}
I would like to access to the value of the "BusinessName" using key and not index so if I put : echo $arrayOfValue[0][1]; it gives me the BusinessName that is ITCompany but if I put
: echo $arrayOfValue['BusinessName'][1]; it gives nothing so how can I fix that please?
The array is initialized $arrayOfValue = array(); and then populated dynamically inside a for loop like that
$arrayOfValue[] = array($Label, $Value);
your array has this kind of data
$arrayOfPostsValue[] = array("BusinessName","ITCompany");
$arrayOfPostsValue[] = array("Address","29 xxxxxx,Canada");
$arrayOfPostsValue[] = array("PrimaryBusinessPhone","(444) 111-1111");
$arrayOfPostsValue[] = array("BusinessEmail","xx#example.com");
there is no array key in data So, you have to recreate your desire array
$newArrayOfPostsValue = array();
foreach ( $arrayOfPostsValue as $value ){
$newArrayOfPostsValue[$value[0]] = $value[1];
}
print_r($newArrayOfPostsValue);
and here is output
Array
(
[BusinessName] => ITCompany
[Address] => 29 xxxxxx,Canada
[PrimaryBusinessPhone] => (444) 111-1111
[BusinessEmail] => xx#example.com
)
As mentioned in the comment, change the structure of the array, it will be much easier to handle
$my_array = array(
array('Business Name' => 'It Company'),
array('Address' => 'My address')
);
Looking at the content of your array, I will restructure it as
$my_improved_array = array(
'BusinessName' => 'It Company',
'Address' => 'My Address',
);
This is how you can access,
echo $my_array[0]['BusinessName'] //prints 'It Company'
echo $my_array[1]['Address'] //prints 'My Address'
echo $my_improved_array['BusinessName'] // prints 'It Company'
Try like this and save array as key value pairs and then access the key:
foreach($arrayOfValues as $a)
$arr[$a[0]] = $a[1];
echo $arr['BusinessName'];
While creating that array build it with index as BusinessName
array (
0 => array(
'BusinessName'=> "ITCompany"
)
1 => array(1) (
'Address'=> "29 xxxxxx,Canada"
)
)
etc..
PHP Array example
$array = array();
$array['BusinessName'] = 'ITCompany';
$array['Address'] = '29 xxxxxx,Canada';
And so on... Now you can echo values with
echo $array['BusinessName'];
Also this works
$array = array('BusinessName' => 'ITCompany', 'Address' => '29 xxxxxx,Canada');
First of all, how are you building this array ? Maybe you can directly make a workable array.
Anyway, you can do something like this :
$oldArray = Array(
Array("BusinessName", "ITCompany"),
Array("Address", "29 xxxxxx,Canada"),
Array("PrimaryBusinessPhone", "(444) 111-1111"),
Array("BusinessEmail", "xx#example.com")
);
$newArray = Array();
foreach($oldArray as value) {
$newValue[$value[0]] = $value[1];
}
/* Now, it's equal to
$newArray = Array(
"BusinessName" => "ITCompany",
"Address" => "29 xxxxxx,Canada",
"PrimaryBusinessPhone" => "(444) 111-1111",
"BusinessEmail" => "xx#example.com"
);
*/
I know I'm probably missing something easy, but I have a foreach loop and I'm trying to modify the values of the first array, and output a new array with the modifications as the new values.
Basically I'm starting with an array:
0 => A:B
1 => B:C
2 => C:D
And I'm using explode() to strip out the :'s and second letters, so I want to be left with an array:
0 => A
1 => B
2 => C
The explode() part of my function works fine, but I only seem to get single string outputs. A, B, and C.
Sounds like you want something like this?
$initial = array('A:B', 'B:C', 'C:D');
$cleaned = array();
foreach( $initial as $data ) {
$elements = explode(':', $data);
$cleaned[] = $elements[0];
}
Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself
$arr = array( 0 => 'A:B', 1 => 'B:C', 2 => 'C:D');
// foreach($arr as $val) will not work.
foreach($arr as &$val) { // prefix $val with & to make it a reference to actual array values and not just copy a copy.
$temp = explode(':',$val);
$val = $temp[0];
}
var_dump($arr);
Output:
array(3) {
[0]=>
string(1) "A"
[1]=>
string(1) "B"
[2]=>
&string(1) "C"
}