I have array:
$array = [
'aaa 3',
'bbb 15',
'ccccc 3A',
'dddd 2412',
'eee fff 15',
'ggg 612',
'hhh iiiii 23B',
];
I would like receive:
$name = 'aaa'; $number = '3';
$name = 'bbb'; $number = '15';
$name = 'ccccc'; $number = '3A';
$name = 'dddd'; $number = '2412';
$name = 'eee'; $number = '15';
$name = 'ggg'; $number = '612';
$name = 'hhh iiiii'; $number = '23B';
So I do:
foreach ($array as $item) {
$expl = explode(' ', $item);
$name = $expl[0];
$number = $expl[1];
}
But this not working for eee fff 15 and hhh iiiii 23B, because these names has two parts. How is better way for this?
Use a regex:
<?php
$array = [
'aaa 3',
'bbb 15',
'ccccc 3A',
'dddd 2412',
'eee fff 15',
'ggg 612',
'hhh iiiii 23B',
];
$regex = '#(?<word>.+)\s(?<number>.+)#';
$results = [];
foreach ($array as $line) {
preg_match($regex, $line, $matches);
$results[$matches['word']] = $matches['number'];
}
var_dump($results);
2 capture groups, first is any characters .+, then a space \s, then any characters .+
Output:
array(7) { ["aaa"]=> string(1) "3" ["bbb"]=> string(2) "15" ["ccccc"]=> string(2) "3A" ["dddd"]=> string(4) "2412" ["eee fff"]=> string(2) "15" ["ggg"]=> string(3) "612" ["hhh iiiii"]=> string(3) "23B" }
See it working here: https://3v4l.org/t2tMd
You need to look at the size of the array and pick only the last for the number and the rest for the name...
foreach ($array as $item) {
$expl = explode(' ', $item);
$name = implode(" ", array_slice($expl,0,-1));
$number = $expl[count($expl)-1];
echo $name."=". $number.PHP_EOL;
}
Bit late to the party but I wanted to throw in my suggestion on how to do this.
If the $number you want is always at the end of the array, then it doesn't matter how big $name is
$newArray = array();
foreach ($array as $item) {
$expl = explode(' ', $item);
//get the size of the array
$last= count($expl)-1;
//get the final element in the array
$number = $expl[$last];
//remove the last element from array
unset($expl[$last]);
//glue it back together
$name = implode(" ",$expl);
//set the name + number in our array
$newArray[]=array('name' => $name,'number'=>$number);
}
print_r($newArray);
//Output:
/* Array (
[0] => Array (
[name] => aaa
[number] => 3
)
[1] => Array (
[name] => bbb
[number] => 15
)
[2] => Array (
[name] => ccccc
[number] => 3A
)
[3] => Array (
[name] => dddd
[number] => 2412
)
[4] => Array (
[name] => eee fff
[number] => 15
)
[5] => Array (
[name] => ggg
[number] => 612
)
[6] => Array (
[name] => hhh iiiii
[number] => 23B
)
)
*/
try this,
foreach ($array as $item) {
$expl = explode(' ', $item);
$division=array_pop($expl);
$name = $expl[0].' '.$expl[1];
$number = $division;
}
Related
I am using PHP 7.3.5 and I have the following set of array values:
$valueArr = ['-4.2%', '51.0', '90K', '0.5%', '0.74|2.6', '-1.2B', '779B', '215K', '92.2%', '42.8B', '1.49T', '1690B', '-10.8B', '0.38|3.9', '102.4', '1.00%', '0.07|1.3'];
Basically I want for each of these values the number and the "type", so if it is a percentage then I would like to get -4.2 and percentage.
I tried to create a minimum example (however the below code is no real good example ;( ), but I am stuck at the data structure level as some array keys have two inputs, such as '0.74|2.6':
<?php
$valueArr = ['-4.2%', '51.0', '90K', '0.5%', '0.74|2.6', '-1.2B', '779B', '215K', '92.2%', '42.8B', '1.49T', '1690B', '-10.8B', '0.38|3.9', '102.4', '1.00%', '0.07|1.3'];
$resArr = array();
$structureArr = array(
'value1' => "",
'number1' => "",
'value2' => "",
'number2' => ""
);
foreach ($valueArr as $key => $v) {
if (1 === preg_match('/%/', $valueArr[$key])) {
preg_match('!\d+\.*\d*!', $valueArr[$key], $structureArr['number1']);
$structureArr['value1'] = 'percentage';
}
/*
if (1 === preg_match('|', $valueArr[$key])) {
$str = explode("|", $valueArr[$key]);
$value1 = 'number';
$number1 = $str[0];
$value2 = 'number';
$number2 = $str[1];
}
if (1 === preg_match('', $valueArr[$key])) {
}
*/
array_push($resArr, $structureArr);
}
print_r($resArr);
/*
Wanted Result
Array
(
[0] => Array
(
[0] => -4.2
[1] => 'percentage'
)
[1] => Array
(
[0] => 51.0
[1] => 'number'
)
[2] => Array
(
[0] => 90000
[1] => number
)
[3] => Array
(
[0] => 0.5
[1] => percentage
)
[4] => Array
(
[0] => 0.74
[1] => number
[2] => 2.6
[3] => number
)
...
*/
I would highly appreciate your input on how to structure this array input.
Appreciate your replies!
If you join the array on a space and replace pipes | with a space, then you have a list of numbers and their symbol (if any) separated by a space. Then just match your numbers and whatever symbol comes after it. Then you just match the number index with the symbol index. I used an array to map the symbol to the word and number if none:
$string = str_replace('|', ' ', implode(' ', $valueArr));
preg_match_all('/([\d.-]+)([^\s]*)/', $string, $matches);
$types = ['%'=>'percent','K'=>'thousand','M'=>'million','B'=>'billion','T'=>'trillion'];
foreach($matches[1] as $k => $v) {
$t = $types[$matches[2][$k]] ?? 'number';
$result[] = [$v, $t];
}
This yields an array like this, with each number that was joined by a pipe with it's own element:
Array
(
[0] => Array
(
[0] => -4.2
[1] => percent
)
[1] => Array
(
[0] => 51.0
[1] => number
)
[2] => Array
(
[0] => 90
[1] => thousand
)
///etc...
If you need a floating point number then just change:
$result[] = [(float)$v, $t];
This expands on my comment. Not sure if it's the most optimal solution or not.
Rough outline...
Create array mapping suffix to multiplier. Loop through source array. explode on |. Loop through result. If last character is %, strip it, value=value and type=percentage, else, strip last char, use it as array index (if it is an available index), value=value*multiplier and type=number.
$resArr = array();
$multipliers = array("K" => 1000, "M" => 1000000, "B" => 1000000000, "T" => 1000000000000);
$valueArr = ['-4.2%', '51.0', '90K', '0.5%', '0.74|2.6', '-1.2B', '779B', '215K', '92.2%', '42.8B', '1.49T', '1690B', '-10.8B', '0.38|3.9', '102.4', '1.00%', '0.07|1.3'];
foreach($valueArr as $index => $value)
{
$parts = explode("|", $value);
$resArr[$index] = array();
foreach($parts as $part)
{
$lastChar = substr($part, -1);
if($lastChar == "%")
{
$resArr[$index][] = substr($part, 0, -1);
$resArr[$index][] = "percentage";
}
else if(in_array($lastChar, array_keys($multipliers)))
{
$multiple = $multipliers[$lastChar];
$resArr[$index][] = (substr($part, 0, -1))*$multiple;
$resArr[$index][] = "number";
}
else
{
$resArr[$index][] = $part;
$resArr[$index][] = "number";
}
}
}
var_dump($resArr);
DEMO
I have a text file which I must read, and use the data from.
3
sam 99912222
tom 11122222
harry 12299933
sam
edward
harry
How can I create an array of these strings in the following form?
array(
"name" => "number"
...
)
I tried this:
$handle = fopen("file.txt", "r");
fscanf($handle, "%d %d", $name, $number);
What then? No matter what I try, it only works for the first line.
sam 99912222
Added codes to have both types of output - ignoring and including the lines that don't have name-value pairs. Check them out below
This code goes through each line and gets only the ones that have both name and value (something[space]something)):
//$lines = ... each line of the file in an array
$vals = array();
foreach($lines as $v){
$tmp = explode(' ', $v);
if(count($tmp) > 1){
$vals[trim($tmp[0])] = trim($tmp[1]); // trim to prevent garbage
}
}
print_r($vals);
It will output this:
Array
(
[sam] => 99912222
[tom] => 11122222
[harry] => 12299933
)
See the code in action here.
If you need the values even if they didn't come in pairs, do it like this:
//$lines = ... each line of the file
$vals = array();
foreach($lines as $v){
$tmp = explode(' ', $v);
$name = '';
$number = '';
$tmp[0] = trim($tmp[0]);
if(count($tmp) > 1){
$name = $tmp[0];
$number = trim($tmp[1]);
}else{
if(is_numeric($tmp[0])){
$number = $tmp[0];
}else{
$name = $tmp[0];
}
}
$vals[] = array(
'name' => $name,
'number' => $number
);
}
print_r($vals);
And the output:
Array
(
[0] => Array
(
[name] =>
[number] => 3
)
[1] => Array
(
[name] => sam
[number] => 99912222
)
[2] => Array
(
[name] => tom
[number] => 11122222
)
[3] => Array
(
[name] => harry
[number] => 12299933
)
[4] => Array
(
[name] => sam
[number] =>
)
[5] => Array
(
[name] => edward
[number] =>
)
[6] => Array
(
[name] => harry
[number] =>
)
See the code in action here.
Data in file are inconsistent, best of is to use regex to identify what data you've got from each line.
$lines = file('file.txt'); // this will open file and split them into lines
$items = array();
foreach($lines as $line){
$name = null;
$number = null;
$nameFound = preg_match("|([A-Za-z]+)|", $line, $matches);
if($nameFound){
$name = $matches[0];
}
$numberFound = preg_match("|([0-9]+)|", $line, $matches);
if($numberFound){
$number = $matches[0];
}
$items[] = array('name' => $name, 'number' => $number);
}
Then in items you should find parsed data from file.
To make it just extract full format data just change lines with regex into one line like this:
$lines = file('file.txt'); // this will open file and split them into lines
$items = array();
foreach($lines as $line){
$userFound = preg_match("/([A-Za-z]+) ([0-9]+)/", $line, $matches);
if($userFound){
$items[$matches[1]] = $matches[2];
}
}
With the Algorithm below, you can simply parse each individual line of the Text-File Contents into an array with the 1st Word or Digit(s) on each line as the Key and the 2nd Word as the Value. When the 2nd word or group of words do not exist, a NULL is assigned to that Key. For re-usability, this algorithm has been encapsulated into a Function. Here you go:
<?php
function parseTxtFile($txtFile){
$arrTxtContent = [];
if(!file_exists($txtFile)){ return null;}
$strFWriteTxtData = file_get_contents($txtFile);
if(empty($strFWriteTxtData)){return null;}
$arrFWriteInfo = explode("\n", $strFWriteTxtData);
foreach($arrFWriteInfo as $iKey=>$lineData){
$arrWriteData = explode(", ", $lineData);
foreach($arrWriteData as $intKey=>$strKeyInfo){
preg_match("#(^[a-z0-9_A-Z]*)(\s)(.*$)#i", $strKeyInfo, $matches);
preg_match("#(^[a-z0-9_A-Z]*)(\s*)?$#i", $strKeyInfo, $matches2);
if($matches) {
list(, $key, $null, $val) = $matches;
if (!array_key_exists($key, $arrTxtContent)) {
$arrTxtContent[$key] = $val;
}else{
$iKey = $intKey + 1;
$key = $key . "_{$iKey}";
$arrTxtContent[$key] = $val;
}
}else if($matches2) {
list(, $key, $null) = $matches2;
if (!array_key_exists($key, $arrTxtContent)) {
$arrTxtContent[$key] = null;
}else{
$key = preg_match("#_\d+#", $key, $match)? $key . $match[0] : "{$key}_1";
$arrTxtContent[$key] = null;
}
}
}
}
return $arrTxtContent;
}
var_dump(parseTxtFile(__DIR__ . "/data.txt"));
Just call the function parseTxtFile($txtFile) passing it the path to your text File and it will return an Array that looks something like below:
array (size=7)
3 => null
'sam' => string '99912222' (length=8)
'tom' => string '11122222' (length=8)
'harry' => string '12299933' (length=8)
'sam_1' => null
'edward' => null
'harry_1' => null
Hope this could help a bit....
Cheers & Good-Luck ;-)
hi i have output of an array as follow:
Array (
[0] => 66, 65, 64
[1] => 57
[2] => 66,23
[3] => 66
)
How can i remove duplication values and convert the collection into comma separated string? The unique output is 66,65,64,57,23. Thanks
Make use of array_unique() and array_reverse():
$array = Array (
0 => '66, 65, 64',
1 => '57',
2 => '66,23',
3 => '66',
);
$collection = array();
foreach($array as $numbers) {
$nums = explode(',', $numbers);
foreach($nums as $num) {
$collection[] = trim($num);
}
}
// unique and sort
$collection = array_unique($collection, SORT_NUMERIC);
// reverse it so that it can be descending order
$collection = array_reverse($collection);
print_r($collection);
which will output :
Array (
[0] => 66
[1] => 65
[2] => 64
[3] => 57
[4] => 23
)
you iterate through the array and add it to a final array by checking its values then implode to construct a string.
$array = Array (
0 => array(66, 65, 64),
1 => array(57),
2 => array(66,23),
3 => array( 66)
);
$final = array();
foreach ($array as $item) {
foreach ($item as $num) {
if (!in_array($num, $final)) $final[] = $num;
}
}
$str = implode(",", $final);
echo $str
well, the code is lil ugly...
$test = [
'0' => '66, 65',
'1' => '80', '66'
];
$temp = implode(',', array_map('trim', array_unique(explode(',', implode(',', $test)))));
print_r($test);
print_r($temp);
//output
Array (
[0] => 66, 65
[1] => 80
[2] => 66
)
66,65,80
Ok:
<?php
$array = array(
"66, 65, 64",
57,
"66,23",
66
);
function dosplit($a,$b) {
if (preg_match("/,/",$b)) {
$a = array_merge($a, preg_split('/\s*,\s*/', $b));
} else {
array_push($a, $b);
}
return $a;
}
$result = array_reduce($array, 'dosplit' ,array());
$array = array_unique($result);
The output is:
Array
(
[0] => 66
[1] => 65
[2] => 64
[3] => 57
[5] => 23
)
This might is useful for you:
$array = array(
"66, 65, 64 ",
"57",
"66,23",
"66",
);
echo "<pre>";
print_r($array);
//to make single line
foreach ($array as $val) {
$singleline.=$val . ",";
}
echo $singleline . "</br>";
//remove the "," end of the value
$endvlaue = rtrim($singleline, ",");
echo $endvlaue;
//make an array
$val = explode(",", $endvlaue);
echo "<pre>";
print_r($val);
echo "<pre>";
//make uniqu
$finalvalue = array_unique($val);
echo "<pre>";
//make , seperator
print_r(implode(",", $finalvalue));
How can the array be separated into groups of identical elements (concatenated chars).
For example, I have this array:
Array(
[0] => 1
[1] => 1
[2] => 1
[3] => 2
[4] => 2
[5] => 1
)
and want to group all identical numbers in only one element, bringing the together with concatenation to get something like this:
Array(
[0] => 111
[1] => 22
[2] => 1
)
To group all identical elements by concatenating them together (will not work for concatenating just the neighboring identical elements)
$arr = array (1,1,1,2,2,1);
$sum = array_count_values($arr);
array_walk($sum, function(&$count, $value) {
$count = str_repeat($value, $count);
});
print_r($sum);
Output
Array (
[1] => 1111
[2] => 22 )
Or for concatenating just the neighboring identical elements
$prev=null;
$key=0;
foreach ( $arr as $value ) {
if ($prev == $value){
$res[$key] .= $value;
} else {
$key++;
$res[$key] = $value;
$prev=$value;
}
}
print_r($res);
Output
Array (
[1] => 111
[2] => 22
[3] => 1 )
Here two functions
1 will return
Array
(
[1] => Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 1
)
[2] => Array
(
[0] => 2
[1] => 2
)
)
as output and second one will return
Array
(
[1] => 1111
[2] => 22
)
as output
$array = array(
1,1,1,2,2,1
);
print_r(groupArray($array));
print_r(groupSame($array));
function groupArray($array){
$temp = array();
foreach($array as $value){
if(!isset($temp[$value])){
$temp[$value] = array();
}
array_push($temp[$value],$value);
}
return $temp;
}
function groupSame($array){
$temp = array();
foreach($array as $value){
if(!isset($temp[$value])){
$temp[$value] = "";
}
$temp[$value] .= $value;
}
return $temp;
}
<?php
$i=0;
foreach($Arrays as $key=>$val) {
if (!isset($array[$i]))
$array[$i]=$val;
else if (!isset($mem) || $val==$mem)
$array[$i]=10*$array[$i]+$mem;
else
$i++;
$mem=$val;
}
?>
$array = array(1,1,1,2,2,1);
$start = "";
$new_array = array();
foreach($array as $v){
$v = (string)$v;
if($start==$v){
$count = count($new_array) - 1;
$val = $new_array[$count].$v;
$new_array[$count] = $val;
} else{
$new_array[] = $v;
}
$start = $v;
}
var_dump($new_array);
Tested and its working..
Output > array(3) { [0]=> string(3) "111" [1]=> string(2) "22" [2]=> string(1) "1" }
$newarray = array_unique($oldarray);
$count = array_count_values($oldarray);
foreach($newarray as &$val){
$val = str_repeat($val,$count[$val]);
}
http://codepad.org/FUf0n8sz
I have an array with each element is a string like this:
$items[0] = "*1*x *2858* in *1* with selected image to print at *http://mysite.com/test.jpg*"
and
$items[1] = "*2*x *2353* in *2* with selected image to print at *http://mysite.com/test1.jpg*"
How can I split this array elements into a 2nd dimension array so that it becomes:
$items[0][quantity] == 1
$items[0][product_id] == 2858
$items[0][variation} == 1
$items[0][selectedImageUrl] == "http://mysite.com/test.jpg"
and
$items[1][quantity] == 2
$items[1][product_id] == 2353
$items[1][variation} == 2
$items[1][selectedImageUrl] == "http://mysite.com/test1.jpg"
Thanks so much for your help!
#Cal
This is what I have when applying your code.
I applied it to my situation and this is what I have:
function parse_my_str($str){
$bits = explode(' ', $str);
$out['selectedImageUrl'] = array_pop($bits);
$out['product_id'] = $bits[1];
$out['variation'] = $bits[3];
$bits = explode('*', $str);
$out['quantity'] = $bits[1];
return $out;
}
$items = explode("||", $_SESSION['mp_shipping_info']['special_instructions']);
foreach ($items as $i => $v) {
$items[$i] = parse_my_str($v);
print_r($items[$i]);
}
But i've got
Array ( [selectedImageUrl] => *http://youparkrudely.com/files/2012/04/2011-Aston-Martin-Rapide-026.jpg* [product_id] => *2858* [variation] => *1* [quantity] => 1 ) Array ( [selectedImageUrl] => [product_id] => [variation] => [quantity] => )
#Cal
Array (
[selectedImageUrl] => *http://youparkrudely.com/files/2012/04/2011-Aston-Martin-Rapide-026.jpg*
[product_id] => *2858*
[variation] => *1*
[quantity] => 1 )
Array ( [selectedImageUrl] => [product_id] => [variation] => [quantity] => )
Updated for new string, using preg_match() instead:
$str = "*1*x *2858* in *1* with selected image to print at *http://mysite.com/test.jpg*";
$arr = parse_my_str($str);
print_r($arr);
function parse_my_str($str){
preg_match_all('!\\*(.*?)\\*!', $str, $m);
return array(
'quantity' => $m[1][0],
'product_id' => $m[1][1],
'variation' => $m[1][2],
'selectedImageUrl' => $m[1][3],
);
}
For your example, you'd use the function like this:
foreach ($items as $k => $v) $items[$k] = parse_my_str($v);
You could go with a preg_match() solution and a regular expression. Not sure if I matched things exactly but here is a simple example.
// Regular Expression
$pattern = '/^\*(\d+)\*x (\d+) in (\d+) with selected image to print at (.+)$/';
preg_match( $pattern, $string, $matches );
if you var_dump() $matches you'll get this:
array(5) {
[0]=> string(74) "*2*x 2353 in 2 with selected image to print at http://mysite.com/test1.jpg"
[1]=> string(1) "2"
[2]=> string(4) "2353"
[3]=> string(1) "2"
[4]=> string(27) "http://mysite.com/test1.jpg"
}
You would have to loop through your array of items.
foreach ( $array as $key => $value ) :
preg_match( $pattern, $value, $matches );
$items[$key]['quantity'] = $matches[1];
$items[$key]['product_id'] = $matches[2];
$items[$key]['variation'] = $matches[3];
$items[$key]['selectedImageURL'] = $matches[4];
endforeach;
I would also suggest a custom function.
If you need some help on regular expression I suggest starting here: http://www.regular-expressions.info/
<?php
$items[0] = "*1*x 2858 in 1 with selected image to print at http://mysite.com/test.jpg";
$items[1] = "*2*x 2353 in 2 with selected image to print at http://mysite.com/test1.jpg";
foreach ($items as $key=>$item){
$temp = explode(" ", $item);
$items[$key] = array();
$items[$key]['quantity'] = $temp[0];
$items[$key]['product_id'] = $temp[1];
$items[$key]['variation'] = $temp[3];
$items[$key]['selectedImageURL'] = $temp[10];
}
print_r($items);
Something along those lines should work. Assuming, of course, that your quantity and variation remain the same.