Remove number from array with repeated digits - php

I want to remove the numbers from array which have repeated digits in them.
array('4149','8397','9652','4378','3199','7999','8431','5349','7068');
to
array('8397','9652','4378','8431','5349','7068');
I have tried this thing
foreach($array as $key => $value) {
$data = str_split($value, 1);
$check = 0;
foreach($data as $row => $element) {
$check = substr_count($value, $element);
if($check != 1) {
array_diff($array, array($value));
}
}
}

You can filter the array using a regular expression that matches:
(.) any character
.* followed by zero or more characters
\1 followed by the first character one more time
Example code:
$array = array('4149','8397','9652','4378','3199','7999','8431','5349','7068');
$result = array_filter(
$array,
function ($number) {
return !preg_match('/(.).*\\1/', $number);
}
);
echo implode(', ', $result), PHP_EOL;
Output:
8397, 9652, 4378, 8431, 5349, 7068

This should work for you:
Here I first str_split() each element into a separate array with array_map(). After this I just compare the splitted array with the same array just with array_unique() digits and check if they are the same. If yes I return the implode() number otherwise false. And at the end I just filter the elements with false with array_filter() out.
So in other words I just compare these 2 arrays with they are the same:
array1:
Array
(
[0] => Array
(
[0] => 4
[1] => 1
[2] => 4
[3] => 9
)
//...
)
array2:
Array
(
[0] => Array
(
[0] => 4
[1] => 1
[3] => 9
)
//...
)
Code:
<?php
$arr = ['4149', '8397', '9652', '4378', '3199', '7999', '8431', '5349', '7068'];
$arr = array_map("str_split", $arr);
$result = array_filter(array_map(function($v1, $v2){
return ($v1 === $v2?implode("", $v1):false);
}, $arr, array_map("array_unique", $arr)));
print_r($result);
?>
output:
Array ( [1] => 8397 [2] => 9652 [3] => 4378 [6] => 8431 [7] => 5349 [8] => 7068 )

Related

Parse diverse array of numbers for value and number

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

Remove unset array containing specific string

I have the following array imported from a CSV:
Array
(
[0] => Array
(
[0] => QUARTERLY STATS;Q1/2011;Q2/2011;Q3/2011;Q4/2011;Q1/2012;Q2/2012;Q3/2012;Q4/2012;Q1/2013;Q2/2013;Q3/2013;Q4/2013;Q1/2014
)
[1] => Array
(
[0] => January;7500;8800;9500;10000;10500;11000;11500;12000;12500;13000;13420;13820;14200
)
[2] => Array
(
[0] => ;;17
[1] => 30%;8%;5
[2] => 30%;5%;4
[3] => 80%;4
[4] => 50%;4
[5] => 30%;4
[6] => 20%;4%;3
[7] => 20%;3%;2
[8] => 70%
)
[3] => Array
(
[0] => TOTAL;7500;8500;9500;11000;12500;11400;11800;13000;12500;13000;13420;13820;14200
)
[4] => Array
(
[0] => ;;17
[1] => 30%;7
[2] => 95%;5
[3] => 26%;5%;4
[4] => 76%;4
[5] => 55%;4
[6] => 35%;4
[7] => 17%;4%;3
[8] => 23%;2
[9] => 98%;2
[10] => 75%
)
So,
I would like to get rid of all arrays containing "% and TOTAL".
I thought to loop through and unset the matching case:
$remove ="TOTAL";
foreach ($csv as $key => $value){
if (in_array($remove,$value[$key])){
unset($value[$key]);
}
}
This is the error I got:
Warning: in_array() expects parameter 2 to be array, null given
My PHP Version 5.3.10
Would you do it that way or would you use the array_filter?
I am browsing since 2 hours the forum but I could not find any hint helping me out.
Cheers.
You can try by preg_replace for removing TOTAL & %. If you want to remove the element from array then use unset & finally use array_filter for removing null elements.
$newArr = array();
foreach($arr as $key=>$value){
foreach($value as $k=>$v){
$newArr[$key][$k] = preg_replace('/(TOTAL)|(%)/', '', $v); //for removing TOTAL & %
unset($arr[$key][$k]); //for unset the array elements that contains TOTAL & %
}
}
//Output by replacement
print '<pre>';
print_r($newArr);
print '</pre>';
//output after using unset
print '<pre>';
print_r(array_filter($arr));
print '</pre>';
In your case:
foreach ($csv as $subArray)
{
for ($i = 0, $len = count($subArray); $i < $len; $i++)
{
if (strpos($subArray[$i], $remove) !== false)
unset($subArray[$i])
}
}
Comments:
strict comparasion for strpos, if we use !=, then 0 position would be equals to false.
inner loop is "for-loop" bevause it's better to avoid changing content of array inside foreach.
$arr[][] = ("QUARTERLY STATS;Q1/2011;Q2/2011;Q3/2011;Q4/2011;Q1/2012;Q2/2012;Q3/2012;Q4/2012;Q1/2013;Q2/2013;Q3/2013;Q4/2013;Q1/2014");
$arr[][] = ("January;7500;8800;9500;10000;10500;11000;11500;12000;12500;13000;13420;13820;14200");
$arr[] = array(";;17","30%;8%;5","30%;5%;4","80%;4","50%;4","30%;4","20%;4%;3","20%;3%;2","70%");
$arr[][] = ("TOTAL;7500;8500;9500;11000;12500;11400;11800;13000;12500;13000;13420;13820;14200");
$arr[] = array("30%;7","95%;5","26%;5%;4","76%;4","55%;4","35%;4","17%;4%;3","23%;2","98%;2","75%");
$newArr = array();
foreach($arr as $key=>$value) {
foreach($value as $k=>$v) {
$newArr[$key][$k] = preg_replace('/(TOTAL)|(%)/', '', $v); //for removing TOTAL & %
unset($arr[$key][$k]); //for unset the array elements that contains TOTAL & %
}
unset($arr[$key]); // IT does not unset ARR[2] ARR[3] and ARR[4] containing TOTAL & %
}
Output by replacement
print '<pre>';
print_r($newArr);
print '</pre>';
Output after using unset
print '<pre>';
print_r(array_filter($arr));
print '</pre>';
I did create exactly the same ARRAY as imported from CSV.
unset does not unset ARRAY2,3,4 which is containing TOTAL AND %.
unset does not unset ARRAY2,3,4 which is containing TOTAL AND %.

Explode multiple comma-separated strings in a 2d array, then get all unique values

I have an 2d array which returns me this values:
Array (
[0] => Array (
[0] => wallet,pen
[1] => perfume,pen
)
[1] => Array (
[0] => perfume, charger
[1] => pen,book
).
Out of this i would like to know if it is possible to create a function which would combine the array going this way,and create a new one :
if for example [0] => Array ( [0] => wallet,pen [1] => perfume,pen ) then should be equal to
[0] => Array ( [0] => wallet,pen, perfume ) because there is a common word else do nothing.
And also after that retrieve each words as strings for further operations.
How can i make the values of such an array unique. Array ( [0] => Array ( [0] => wallet [1] => pen [2] => perfume [3] => pen) ) as there is pen twice i would like it to be deleted in this way ( [0] => Array ( [0] => wallet [1] => pen [2] => perfume) )
It's just a matter of mapping the array and combining the inner arrays:
$x = [['wallet,pen', 'perfume,pen'], ['perfume,charger', 'pen,book']];
$r = array_map(function($item) {
return array_unique(call_user_func_array('array_merge', array_map(function($subitem) {
return explode(',', $subitem);
}, $item)));
}, $x);
Demo
This first splits all the strings based on comma. They are then merged together with array_merge() and the duplicates are removed using array_unique().
See also: call_user_func_array(), array_map()
Try this :
$array = Array (Array ( "wallet,pen", "perfume,pen" ), Array ( "perfume, charger", "pen,book" ));
$res = array();
foreach($array as $key=>$val){
$temp = array();
foreach($val as $k=>$v){
foreach(explode(",",$v) as $vl){
$temp[] = $vl;
}
}
if(count(array_unique($temp)) < count($temp)){
$res[$key] = implode(",",array_unique($temp));
}
else{
$res[$key] = $val;
}
}
echo "<pre>";
print_r($res);
output :
Array
(
[0] => wallet,pen,perfume
[1] => Array
(
[0] => perfume, charger
[1] => pen,book
)
)
You can eliminate duplicate values while pushing them into your result array by assigning the tag as the key to the element -- PHP will not allow duplicate keys on the same level of an array, so any re-encountered tags will simply be overwritten.
You can use recursion or statically written loops for this task.
Code: (Demo)
$result = [];
foreach ($array as $row) {
foreach ($row as $tags) {
foreach (explode(',', $tags) as $tag) {
$result[$tag] = $tag;
}
}
}
var_export(array_values($result));
Code: (Demo)
$result = [];
array_walk_recursive(
$array,
function($v) use(&$result) {
foreach (explode(',', $v) as $tag) {
$result[$tag] = $tag;
}
}
);
var_export(array_values($result));

Find in array and get count of each string

I am fetching some data from the db and then push them to an array. I need to find the count of some strings and print out the result (count) in an efficient way:
Array
(
[0] => q1-1,q2-2,q3-2,q4-1,q5-2,q6-3,q7-1,q8-4,
[1] => q1-1,q2-2,q3-1,q4-3,q5-3,q6-3,q7-2,q8-1,
[2] => q1-1,q2-1,q3-1,q4-1,q5-1,q6-2,q7-2,q8-2,
[3] => q1-3,q2-1,q3-1,q4-1,q5-2,q6-3,q7-1,q8-1,
[4] => q1-2,q2-2,q3-3,q4-1,q5-3,q6-3,q7-1,q8-1,
[5] => q1-1,q2-2,q3-3,q4-1,q5-2,q6-3,q7-1,q8-1,
[6] => q1-3,q2-1,q3-1,q4-3,q5-2,q6-3,q7-2,q8-4,
[7] => q1-2,q2-2,q3-3,q4-1,q5-2,q6-5,q7-1,q8-1,
[8] => q1-1,q2-1,q3-2,q4-3,q5-3,q6-5,q7-1,q8-1,
[9] => q1-2,q2-1,q3-1,q4-1,q5-3,q6-3,q7-1,q8-1,
[10] => q1-3,q2-2,q3-3,q4-3,q5-4,q6-3,q7-1,q8-1,
...
)
Sample data is above.
I need to know how many occurences of q1-1, q1-2 ... q8-4 is in the array and print out readable version. Ex. The are 23: q1-1, 412: q1-2 and so on.
I was going to create an array of each string that needs to be searched that iterate through the array. For every result increment the resultVariable for that string but I'm not sure if that's the best way.
Suggestions?
Pretty simple, loop on your array, create sub arrays, and create a counter array:
$counts = array () ;
foreach ( $your_array as $row ) {
$sub = explode(',', $row);
foreach ( $sub as $subval ) {
if ( array_key_exists ( $subval, $counts ) ) {
$counts[$subval] ++ ;
} else {
$counts[$subval] = 1 ;
}
}
}
Here is $counts:
Array (
'q1-1' => 23,
'q1-2' => 9,
// and so on....
);
Try:
$arr = array(...); //your array
$count = array();
foreach($arr as $v) {
$substr = explode(',', $v);
foreach($substr as $m) {
if(strstr($v, $m) !== FALSE)
$count[$m]++;
}
}
Printing the counts,
foreach($count as $k => $v)
echo "Count for '$k': ". $v;

merge array items specific array items

I got this array:
array (
0 => 'K.',
1 => 'Vrachtschip',
2 => 'L.',
3 => 'Gevechtsschip',
4 => 'Z.',
5 => 'Gevechtsschip',
6 => 'Kruiser',
7 => 'Slagschip',
8 => 'Bommenwerper',
9 => 'Vernietiger',
10 => 'Interceptor.',
)
of can I merge the items [0] with [1], because K. vrachtschip must be together.
same ass [2] and [3]; and [4] with [5]. if there is 1 letter and then a dot (k.) it must be merged with the following array item.
Anyone that can help me :)?
How about:
$arr = array (
'K.',
'Vrachtschip',
'L.',
'Gevechtsschip',
'Z.',
'Gevechtsschip',
'Kruiser',
'Slagschip',
'Bommenwerper',
'Vernietiger',
'Interceptor',
'B.',
);
$concat = '';
$result = array();
foreach ($arr as $elem) {
if (preg_match('/^[A-Z]\.$/', $elem)) {
$concat = $elem;
continue;
}
$result[] = $concat.$elem;
$concat = '';
}
if ($concat) $result[] = $concat;
print_r($result);
output:
Array
(
[0] => K.Vrachtschip
[1] => L.Gevechtsschip
[2] => Z.Gevechtsschip
[3] => Kruiser
[4] => Slagschip
[5] => Bommenwerper
[6] => Vernietiger
[7] => Interceptor
[8] => B.
)
Try to use a regular expression to test all entries of your array.
If an occurence is founded, concat the value of your entrie with the next.
I would try something like this:
for($idx=0, $max = count($array_in); $idx < $max; $idx++)
{
if(preg_match('/^[a-z]\.$/i', $array_in[$idx]))
{
$array_out[] = $array_in[$idx].$array_in[$idx+1];
$idx++;
}
else
{
$array_out[] = $array_in[$idx];
}
}
I'd probably do the following (pseudo code):
Create empty array for result
Iterate the original array
For each value: does it match /^[a-z]\.$/i?
If yes, see if original array contains a next element?
If yes, concatenate the two items and add to resulting array, skip next item in loop
If no (pt. 4 or 5) add directly to resulting array.

Categories