I have an source data separated by , but some cases in the its elements contains ,
$A = Array
(
[0] => Array
(
[0] => ",123, abc , company , Inc., 3043, 200, USD",// [123], [abc] , [company , Inc.], [3043], [200], [USD]
[1] => ",456, def , company,Inc., 3043, 200, USD"
)
)
By could not change the data source.( company , Inc., is always fixed array orders )
foreach ($A as $key=>$value){
foreach($value as $k=>$v){
$line = str_replace(',', ';', $v);
$row = explode(',', $line);
list($a, $b, $c, $d, $e, $f) = $row;
}
}
EDIT:
RULE:
yes , the order of company , Inc always fixed and the number of , always 6
$array = explode(',', trim($string, ','));
while (count($array) > 6) {
$array[3] = $array[3] . ',' . $array[4];
unset($array[4]);
$array = array_merge($array);
}
Just a short description: We merge the 3rd and 4th element together, as long as there are more than 6 elements.
Another a little bit more straight forward solution:
$array = explode(',', trim($string, ','));
$result = array_slice($array, 0, 2);
$result[] = implode(',', array_slice($array, 2, - 3));
$result = array_merge($result, array_slice($array, -3));
Made you a simple function that does it. The only reason I create $foo,$bar,$baz is so you can easily use foreach and keep the order.
function parse($str){
$parts=explode(',',$str,4);
$result=array($parts[1],$parts[2]);
$parts=explode(',',$parts[3]);
$foo=array_pop($parts);
$bar=array_pop($parts);
$baz=array_pop($parts);
$result[2]=implode(',',$parts);
$result[3]=$baz;
$result[4]=$bar;
$result[5]=$foo;
return $result;
}
Change the source data to contain quotes around the values, e.g. change it to
[0] => '"123", "abc" , "company , Inc.", "3043", "200", "USD"'
Then use str_getcsv.
Related
This question already has answers here:
PHP - split String in Key/Value pairs
(5 answers)
Convert backslash-delimited string into an associative array
(4 answers)
Closed 12 months ago.
i have a string like
$str = "1-a,2-b,3-c";
i want to convert it into a single array like this
$array = [
1 => "a",
2 => "b",
3 => "c"
];
what i do is
$str = "1-a,2-b,3-c";
$array = [];
$strex = explode(",", $str);
foreach ($strex as $str2) {
$alphanumeric = explode("-", $str2);
$array[$alphanumeric[0]] = $alphanumeric[1];
}
can i do this in a better way?
You can use preg_match_all for this:
<?php
$str = "1-a,2-b,3-c";
preg_match_all('/[0-9]/', $str, $keys);
preg_match_all('/[a-zA-Z]/', $str, $values);
$new = array_combine($keys[0], $values[0]);
echo '<pre>'. print_r($new, 1) .'</pre>';
here we take your string, explode() it and then preg_match_all the $value using patterns:
/[0-9]/ -> numeric value
/[a-zA-Z]/ -> letter
then use array_combine to get it into one array
Thanks to u_mulder, can shorten this further:
<?php
$str = "1-a,2-b,3-c";
preg_match_all('/(\d+)\-([a-z]+)/', $str, $matches);
$new = array_combine($matches[1], $matches[2]);
echo '<pre>'. print_r($new, 1) .'</pre>';
just a little benchmark:
5000 iterations
Debian stretch, php 7.3
parsed string: "1-a,2-b,3-c,4-d,5-e,6-f,7-g,8-h,9-i"
[edit] Updated with the last 2 proposals [/edit]
You can use preg_split with array_filter and array_combine,
function odd($var)
{
// returns whether the input integer is odd
return $var & 1;
}
function even($var)
{
// returns whether the input integer is even
return !($var & 1);
}
$str = "1-a,2-b,3-c";
$temp = preg_split("/(-|,)/", $str); // spliting with - and , as said multiple delim
$result =array_combine(array_filter($temp, "even", ARRAY_FILTER_USE_KEY),
array_filter($temp, "odd",ARRAY_FILTER_USE_KEY));
print_r($result);
array_filter — Filters elements of an array using a callback function
Note:- ARRAY_FILTER_USE_KEY - pass key as the only argument to callback instead of the value
array_combine — Creates an array by using one array for keys and another for its values
Demo
Output:-
Array
(
[1] => a
[2] => b
[3] => c
)
One way to do with array_map(),
<?php
$my_string = '1-a,2-b,3-c';
$my_array = array_map(function($val) {list($key,$value) = explode('-', $val); return [$key=>$value];}, explode(',', $my_string));
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($my_array)) as $k=>$v){
$result[$k]=$v;
}
print_r($result);
?>
WORKING DEMO: https://3v4l.org/aYmOH
Tokens all the way down...
<?php
$str = '1-a,2-b,3-c';
$token = '-,';
if($n = strtok($str, $token))
$array[$n] = strtok($token);
while($n = strtok($token))
$array[$n] = strtok($token);
var_export($array);
Output:
array (
1 => 'a',
2 => 'b',
3 => 'c',
)
Or perhaps more terse without the first if...:
$array = [];
while($n = $array ? strtok($token) : strtok($str, $token))
$array[$n] = strtok($token);
Not a better way but one more example:
$str = "1-a,2-b,3-c";
$arr1 = explode(",", preg_replace("/\-([a-zA-Z]+)/", "", $str));
$arr2 = explode(",", preg_replace("/([0-9]+)\-/", "", $str));
print_r(array_combine($arr1, $arr2));
Mandatory one-liner (your mileage may vary):
<?php
parse_str(str_replace([',', '-'], ['&', '='], '1-a,2-b,3-c'), $output);
var_export($output);
Output:
array (
1 => 'a',
2 => 'b',
3 => 'c',
)
You can do one split on both the , and -, and then iterate through picking off every other pair ($k&1 is a check for an odd index):
<?php
$str = '1-a,2-b,3-c';
foreach(preg_split('/[,-]/', $str) as $k=>$v) {
$k&1 && $output[$last] = $v;
$last = $v;
}
var_export($output);
Output:
array (
1 => 'a',
2 => 'b',
3 => 'c',
)
The preg_split array looks like this:
array (
0 => '1',
1 => 'a',
2 => '2',
3 => 'b',
4 => '3',
5 => 'c',
)
This one explodes the string as the OP has on the comma, forming the pairs: (1-a) and (2-b) etc. and then explodes those pairs. Finally array_column is used to create the associated array:
<?php
$str = '1-a,2-b,3-c';
$output =
array_column(
array_map(
function($str) { return explode('-', $str); },
explode(',', $str)
),
1,
0
);
var_export($output);
Output:
array (
1 => 'a',
2 => 'b',
3 => 'c',
)
My array is :
$array= array(4,3,4,3,1,2,1);
And I'd like to output it like below:
Output = 2
(As 2 is present only once)
This is what I've tried:
$array = array(4, 3, 4, 3, 1, 2, 1);
$array1 = array(4, 3, 4, 3, 1, 2, 1);
$array_diff = array_diff($array, $array1);
*Read last section of this an for the most stable technique the avoids fringe case issues -- it is also the most verbose.
One-liner with no loops: (Demo)
var_export(array_keys(array_intersect(array_count_values($array),[1])));
The breakdown:
array_keys( // return the remaining keys from array_count_values
array_intersect( // filter the first array by second
array_count_values($array), // count number of occurrences of each value
[1] // identify the number of occurrences to keep
)
)
if you (or any future reader) wants to keep more values, replace the second parameter/array in array_intersect().
for instance:
you want to keep 1,2,and 3: array(1,2,3) or [1,2,3]
p.s. For the record, you can use array_filter() with a custom function to omit all non-1 count values, but I have used array_intersect() because the syntax is more brief and IMO easier to read.
p.s. thought I'd revisit and include a PHP7.4 technique and compare against other function-based techniques...
Code: (Demo)
$numbers = [4, 3, 4, 3, 1, 2, 1];
var_export(
array_keys(
array_intersect(
array_count_values($numbers),
[1]
)
)
);
echo "\n---\n";
var_export(
array_keys(
array_filter(
array_count_values($numbers),
function($count) {
return $count === 1;
}
)
)
);
echo "\n---\n";
// PHP7.4+
var_export(
array_keys(
array_filter(
array_count_values($numbers),
fn($count) => $count === 1
)
)
);
*For similar tasks which have values which are not guaranteed to be integers, array_count_values() will complain with "Warning: array_count_values(): Can only count string and integer values".
Even a classic loop that uses values as first level keys like #LF00's answer will suffer potential side effects due to floats and numeric values being cast as integers automatically.
This means that a more general-use solution would be: (Demo)
$result = [];
foreach ($array as $index => $value) {
foreach ($array as $i => $v) {
if ($value === $v && $index !== $i) {
continue 2; // duplicate found, stop checking this value; do not retain
}
}
$result[] = $value;
}
var_export($result);
You could use the array_count_values() php function.
For example:
$numbers = [4, 3, 4, 3, 1, 2, 1];
// build count array as key = number and value = count
$counter_numbers = array_count_values($numbers);
print_r($counter_numbers);
Output :
Array
(
[4] => 2
[3] => 2
[1] => 2
[2] => 1
)
Then loop through the new array to get non-repeated values :
$unique_numbers = [];
foreach ($counter_numbers as $number => $count) {
if ($count === 1) {
$unique_numbers[] = $number;
}
}
print_r($unique_numbers);
Output :
Array
(
[0] => 2
)
You can do it like this: Count the occurrences of each element, then filter out the occurrences bigger than 1.
$array = [4, 3, 4, 3, 1, 2, 1];
foreach ($array as $v)
{
$arr[$v][] = 1; // doesn't matter if 1 is set to a different value
}
foreach($arr as $k => $v)
{
if (count($v) == 1) {
$o[] = $k;
}
}
print_r($o);
result:
Array
(
[0] => 2
)
If in your scenario there will be only one unique value you could use:
$array= array(4,3,4,3,1,2,1);
$singleValue = array_search(1, array_count_values($array));
var_dump($singleValue) // Outputs: 2
If I have a string like:
123*23*6594*2*-10*12
How can I extract the single numbers, in the string separated by *? That is, I want this output:
a=123, b=23, c=6594, d=2, e=-10, f=12.
Flexible:
$vars = range('a', 'z');
$vals = explode('*', $string);
$result = array_combine(array_slice($vars, 0, count($vals)), $vals);
Result:
Array
(
[a] => 123
[b] => 23
[c] => 6594
[d] => 2
[e] => -10
[f] => 12
)
Just for the sheer fun of setting the result as an iterable (rather than an actual array) with the alpha keys in a slightly different manner:
$data = '123*23*6594*2*-10*12';
function dataseries($data) {
$key = 'a';
while (($x = strpos($data, '*')) !== false) {
yield $key++ => substr($data, 0, $x);
$data = substr($data, ++$x);
}
yield $key++ => $data;
}
foreach(dataseries($data) as $key => $value) {
echo $key, ' = ', $value, PHP_EOL;
}
Requires PHP >= 5.5.0
You can use simple as this :
$str = "123*23*6594*2*-10*12";
$arr = explode("*",$str);
$arr['a']=$arr[0];
$arr['b']=$arr[1];
$arr['c']=$arr[2];
$arr['d']=$arr[3];
$arr['e']=$arr[4];
$arr['f']=$arr[5];
echo "a=" .$arr['a'] ." b=". $arr['b']." c=". $arr['c']." d=". $arr['d']." e=". $arr['e']." f=". $arr['f'];
EDIT:
To accomplish Rizier123 wish :
$str = "123*23*6594*2*-10*12";
$arr = explode("*",$str);
$vars = range('a', 'z');
foreach ($arr as $val => $key){
echo $vars[$val]."=".$key."<br>";
}
something like:
list($a,$b,$c,$d,$e,$f) = explode("*", $str);
Just a guess ;)
I have this comma delimited list 0,0,0,0,5,0,7,8,9,10 and i would like to get rid of the number zero represented as a number on its own right and not the zero in 10.
The list is represented in the variable $str and this is the code i am trying to remove the zero with.
$str;
$myArray = explode(',', $str);
if (($key = array_search('0', $myArray)) !== false) {
unset($myArray[$key]);
}
print_r($myArray);
$csv = implode(', ', $myArray);
echo $csv;
but this gives 0, 0, 0, 5, 0, 7, 8, 9, 10
This code does not do the job as i would have liked.What can i do to get rid of the zeros?.
array_filter comes to the rescue:
$myArray = explode(',', '0,0,0,0,5,0,7,8,9,10');
print_r(array_filter($myArray, function($el) { return $el; }));
// ⇒
/*
Array
(
[4] => 5
[6] => 7
[7] => 8
[8] => 9
[9] => 10
)
*/
Use str_replace function - works great and it is not much different than you code so you wont make changes just you must add str_replace function:
$myArray = explode(',', str_replace(array(' 0,',',0'), '',$str) );
if (($key = array_search('0', $myArray)) !== false) {
unset($myArray[$key]);
}
print_r($myArray);
$csv = implode(', ', $myArray);
echo $csv;
I have a string which is like 1,2,2,3,3,4 etc. First of all, I want to make them into groups of strings like (1,2),(2,3),(3,4). Then how I can make this string to array like{(1,2) (2,3) (3,4)}. Why I want this is because I have a array full of these 1,2 etc values and I've put those values in a $_SERVER['query_string']="&exp=".$exp. So Please give me any idea to overcome this issue or solve.Currently this is to create a group of strings but again how to make this array.
function x($value)
{
$buffer = explode(',', $value);
$result = array();
while(count($buffer))
{
$result[] = sprintf('%d,%d', array_shift($buffer), array_shift($buffer));
}
return implode(',', $result);
}
$result = x($expr);
but its not working towards my expectations
I'm not sure I completely understand. You can create pairs of numbers like:
$string = '1,2,3,4,5,6';
$arr = array_chunk(explode(',', $string), 2);
This will give you something like:
array(
array(1, 2),
array(3, 4),
array(5, 6)
)
If you wanted to turn them into a query string, you'd use http_build_query with some data massaging.
Edit: You can build the query like this (100% UNtested):
$numbers = array_map(function($pair) {
return array($pair[0] => $pair[1]);
}, $arr);
$query_string = '?' . http_build_query($numbers);
This:
echo '<pre>';
$str = '1,2,3,4,5,6,7,8';
preg_match_all('/(\d+,\d+)(?=,*)/', $str, $matches);
$pairs = $matches[0];
print_r($pairs);
Outputs:
Array
(
[0] => 1,2
[1] => 3,4
[2] => 5,6
[3] => 7,8
)