I have a array to find sequence of alphabets and then fetch last and first combination. I am trying something like this.
$aarr = ['x','y','z','t','m','n','x','y','z'];
$str = implode('',$aarr);
$all_subset = powerSet($aarr);
foreach ($all_subset as $set) {
$sre_temp = implode('', $set);
$tru = hasOrderedCharactersForward($sre_temp);
if($tru){
echo $sre_temp.'<br>';
}
}
function powerSet($array) {
// add the empty set
$results = array(array());
foreach ($array as $element) {
foreach ($results as $combination) {
$results[] = array_merge(array($element), $combination);
}
}
return $results;
}
function hasOrderedCharactersForward($str, $i = 2) {
$alpha = 'abcdefghijklmnopqrstuvwxyz';
$len = strlen($str);
for($j=0; $j <= $len - $i; $j++){
if(strrpos($alpha, substr($str, $j, $i)) !== false){
return true;
}
}
return false;
}
I think powerSet() is not working like i think. Even it should show 'xyz' as combination but its not;
Have a look at this and make use of it if it fits your needs.
$aarr = ['x','y','z','t','m','n','x','y','z'];
$subsets = [];
$i=0;
#here we merge all chars to sub-sequence
foreach($aarr as $k=>$v){
$subsets[$i][]=$v;
if(isset($aarr[$k+1]) && ord($v)+1!==ord($aarr[$k+1])){
$i++;
}
}
$subsets = array_map(function($a){ return implode('',$a);},$subsets);
print_r($subsets);
Result:
Array ( [0] => xyz [1] => t [2] => mn [3] => xyz )
Getting the first and last value:
#get first
$first=null;
$i=0;
do{
if(strlen($subsets[$i])>1){#find sequence
$first = $subsets[$i];
}
$i++;
}while(!$first && isset($subsets[$i]));
#get last
$last=null;
$i=count($subsets)-1;
do{
if(strlen($subsets[$i])>1){#find sequence
$last = $subsets[$i];
}
$i--;
}while(!$last && isset($subsets[$i]));
print "$first, $last";
Result:
xyz, xyz
Related
I have these for loop to determine consecutive number. What I achieve so far is to print the output in string.
$arr = [1,2,3,6,11,5,4,8,9,3];
for($start=0; $start<=count($arr); $start++){
for($end=$start+1; $end<=count($arr); $end++){
$total = $arr[$end] - $arr[$start];
if($total == 1){
echo 'Number is '.$arr[$start].','.$arr[$end].'<br/>';
} else {
echo '';
}
$arr[$start++];
}
}
My goal is to add the output into array.
I tried to use multidimensional array but no output display.
$arr = [1,2,3,6,11,5,4,8,9,3];
$arr3 = [];
for($start=0; $start<=count($arr); $start++){
for($end=$start+1; $end<=count($arr); $end++){
$total = $arr[$end] - $arr[$start];
if($total == 1){
$arr2 = array();
$arr2[] = $arr[$start].','.$arr[$end].'';
$arr3[] = $arr2;
} else {
}
$arr[$start++];
}
}
echo '<pre>';
print_r($arr3);
echo '</pre>';
exit;
Appreciate if someone can help me. Thanks.
you can simply use array functions, if sorting is important to you as #nice_dev said, you must sort your array before.
$arr = [1,2,3,6,11,5,4,8,9,3];
$cons = [] ;
while (array_key_last($arr) != key($arr)) {
if ((current($arr)+1) == next($arr)) {
prev($arr);
$cons[] = current($arr) . ',' . next($arr);
}
}
print_r($cons);
the output will be :
Array
(
[0] => 1,2
[1] => 2,3
[2] => 8,9
)
You can better sort() the input array first. This way, collecting all consecutive elements would get much simpler. If value at any index isn't +1 of the previous one, we add the $temp in our $results array and start a new $temp from this index.
Snippet:
<?php
$arr = [1,2,3,6,11,5,4,8,9,3];
$result = [];
sort($arr);
$temp = [];
for($i = 0; $i < count($arr); ++$i){
if($i > 0 && $arr[ $i ] !== $arr[$i - 1] + 1){
$result[] = implode(",", $temp);
$temp = [];
}
$temp[] = $arr[$i];
if($i === count($arr) - 1) $result[] = implode(",", $temp);
}
print_r($result);
Online Demo
I am supposed to sort a given array using the following rules:
The sort will need to be case insensitive and place all the characters in alphabetical order first, then numbers, and finally all the other characters, each in the 3 groups following the ASCII order.
I tried "sort" and "natcasesort" functions, but the result is not what I was expecting.
I am supposed to execute my code like this:
./ssap2.php toto tutu 4234 "_hop A2l+ XXX" ## "1948372 AhAhAh"
(sorry for the bad code, this is my first day on PHP :) )
/* function to split the given arguments */
function ft_split($string)
{
$arr = preg_split('/[\s]+/', $string);
return $arr;
}
$brut = array();
$alpha = array();
$numeric = array();
$other = array();
for ($i = 1; $i < $argc; $i++)
{
$brut = array_merge($brut, ft_split($argv[$i]));
}
foreach ($brut as $elem)
{
if (is_numeric($elem))
$numeric[] = $elem;
else if (ctype_alpha($elem))
$alpha[] = $elem;
else
$other[] = $elem;
}
sort($numeric);
natcasesort($alpha);
sort($other);
foreach ($alpha as $word)
echo $word."\n";
foreach ($numeric as $word)
echo $word."\n";
foreach ($other as $word)
echo $word."\n";
?>
I expect something like this:
$> ./ssap2.php toto tutu 4234 "_hop A2l+ XXX" ## "1948372 AhAhAh"
AhAhAh
A2l+
toto
tutu
XXX
1948372
4234
#
_hop
you can try this function :
function ft_compare($s1, $s2)
{
$map = "abcdefghijklmnopqrstuvwxyz0123456789 !\"#$%&'()*+,-./:;<=>?#[\]^_`{|}~";
$s1 = strtolower($s1);
$s2 = strtolower($s2);
$len1 = strlen($s1);
$len2 = strlen($s2);
while ($i < $len1)
{
if ($i >= $len2)
return 1;
$pos1 = strpos($map, $s1[$i]);
$pos2 = strpos($map, $s2[$i]);
if ($pos1 < $pos2)
return -1;
else if ($pos1 > $pos2)
return 1;
$i++;
}
return 0;
}
combined with "usort"
I want to filter the data from the array in a loop. All i want to know is can I use the array_filter inside loop because i am using it and it is not working properly
This is the array which i am getting from DB
Array
(
[0] => Chocolate Manufacturers,C
[1] => ,,,Chocolate Manufacturers,,Chocolate Manufacturers,,Chocolate Manufacturers
[2] =>
)
I am making the array unique by using this code
$num = 2;
for($i=0;$i<count($listing);$i++){
//echo var_export($listing[$i]->cat_title).'<br>';
$listing_cat[$i] = rtrim(ltrim($listing[$i]->cat_title,','),',');
$listing_cat[$i] = explode(',', $listing_cat[$i]);
//$listing_cat[$i] = array_filter(array_keys($listing_cat[$i]), function ($k){ return strlen($k)>=3; });
$listing_cat[$i] = array_filter($listing_cat[$i], function ($sentence){
//divide the each sentence in words
$words = explode(',',$sentence);
$resSentence = [];
//check each words if their length is more then $num
foreach($words as $word){
if(strlen($word) > $num){
$resSentence[] = $word;
}
}
return implode(' ', $resSentence);
});
$listing_cat[$i] = array_unique($listing_cat[$i]);
$listing_cat[$i] = implode(',', $listing_cat[$i]);
$listing_cat[$i] = rtrim(ltrim($listing_cat[$i],','),',');
//$tags['title'][$i] = rtrim(ltrim($listing[$i]->cat_title,','),',');
}
After running this code result is showing like this
Array (
[0] => Chocolate Manufacturers,C
[1] => Chocolate Manufacturers
[2] =>
)
But what i want is to remove the C from the first array i mean to say the unwanted string or string which length will be less than 2 i want to remove that.
Expected Result:
Array (
[0] => Chocolate Manufacturers
[1] => Chocolate Manufacturers
[2] =>
)
i used the below function to remove
$NUM = 2;
$listings[$i] = array_filter($listings[$i], function ($element){
return ($element[$i] > $NUM);
});
But i think because it is in loop it is not working properly. I am placing this code above the array_unique line in loop. All i want is to remove the value which length will be less than 2.
Finally i have achieved my desired answer
$num = 2;
for ($i = 0; $i < count($listing); $i++) {
//$listing_cat[$i] = array_unique($listing[$i]->cat_title);
$listing_cat[$i] = rtrim(ltrim($listing[$i]->cat_title, ','), ',');
$sentence = $listing_cat[$i];
//divide the each sentence in words
$words = explode(',', $sentence);
$resSentence = [];
//check each words if their length is more then $num
foreach ($words as $word) {
if (strlen($word) > $num) {
$resSentence[] = $word;
}
}
$listing_cat[$i] = array_unique($resSentence);
$listing_cat[$i] = implode(',',$listing_cat[$i]);
$listing_cat[$i] = rtrim(ltrim($listing_cat[$i],','),',');
}
echo '<pre>';
print_r($listing_cat);
echo '</pre>';
it is showing perfect result what i want
Array (
[0] => Chocolate Manufacturers
[1] => Chocolate Manufacturers
[2] =>
)
Thanks all for help really appriciated
First of all: I recommend you not to use $listing along with $listings as variable names as it can easily lead to confusion and is not a good readability (especially confusing here on StackOverflow).
Then: You have an error in your code. You are not checking for the length (count) but for the string itself which does resolve in TRUE.
You have:
$NUM = 2;
$listings[$i] = array_filter($listings[$i], function ($element){
return ($element[$i] > $NUM);
}
);
You should have:
$NUM = 2;
$listings[$i] = array_filter($listings[$i], function ($element) use ($NUM) {
return (strlen($element[$i]) >= $NUM);
}
);
You may try the following code:
function arr_filter($arr, $min_length) {
define('STR_MIN_LEN', $min_length);
$arr = array_filter($arr);
$arr_explode = [];
foreach($arr as $value) {
$arr_explode = explode(',', $value);
$arr_explode = array_unique(array_filter($arr_explode));
$arr_explode = array_filter($arr_explode, function($element) {
return strlen($element) >= STR_MIN_LEN;
});
}
return array_values(array_unique($arr_explode));
}
var_dump(arr_filter($arr, 2));
The above code is written as per your requirements. You could try it out and see if it works. This code may not be flexible. You can check it out with various test cases. Hope it works.
EDIT
I assume you have a multidimensional array like:
$arr = array(
array(
'Chocolate Manufacturers,C',
',,,Chocolate Manufacturers,,Chocolate Manufacturers,,Chocolate Manufacturers',
''
),
array(
'Ice Cream Manufacturers,C',
',,,Ice Cream Manufacturers,,Ice Cream Manufacturers,,Ice Cream Manufacturers',
''
)
);
and the code is:
function arr_filter($arr, $min_length) {
define('STR_MIN_LEN', $min_length);
$final_arr = array();
foreach($arr as $value) {
$value = array_filter($value);
$arr_explode = [];
foreach($value as $another_value) {
$arr_explode = explode(',', $another_value);
$arr_explode = array_unique(array_filter($arr_explode));
$arr_explode = array_filter($arr_explode, function($element) {
return strlen($element) >= STR_MIN_LEN;
});
}
$final_arr[] = array_values(array_unique($arr_explode));
}
return $final_arr;
}
var_dump(arr_filter($arr, 2));
I've added this code to make it work with multidimensional array. Hope it works for sure.
EDIT 2
function arr_filter($arr, $min_length) {
define('STR_MIN_LEN', $min_length);
$final_arr = array();
foreach($arr as $value) {
$value = array_filter($value);
$arr_explode_final = [];
foreach($value as $another_value) {
$arr_explode = explode(',', $another_value);
$arr_explode = array_filter($arr_explode, function($element) {
return strlen($element) >= STR_MIN_LEN;
});
// the comma will be added if the string has two different words with comma-separated like `Chocolate Manufacturers, Ice Cream Manufacturers` else comma will be ommited
$arr_explode_final[] = implode(',', array_unique($arr_explode));
}
$final_arr[] = $arr_explode_final;
}
return $final_arr;
}
var_dump(arr_filter($arr, 2));
As you are code say, $listings is contains sentence. If I got your problem properly then, you want to remove smaller from each sentences of the $listings variable.
You can replace your this code:
$NUM = 2;
$listings[$i] = array_filter($listings[$i], function ($element){
return ($element[$i] > $NUM);
});
with the following codeblock:
$num = 2;
$sentence = $listings[$i];
//divide the each sentence in words
$words = explode(',',$sentence);
$resSentence = [];
//check each words if their length is more then $num
foreach($words as $word){
if(strlen($word) > $num){
$resSentence[] = $word;
}
}
$listings[$i] = implode(' ', $resSentence);
Update
I have check out this program below, is it the whole think what you want?
<?php
$listing_cat = ['Chocolate Manufacturers,C', ',,,Chocolate Manufacturers,,Chocolate Manufacturers,,Chocolate Manufacturers', ''];
$num = 2;
for ($i = 0; $i < count($listing_cat); $i++) {
$listing_cat[$i] = rtrim(ltrim($listing_cat[$i], ','), ',');
$sentence = $listing_cat[$i];
//divide the each sentence in words
$words = explode(',', $sentence);
$resSentence = [];
//check each words if their length is more then $num
foreach ($words as $word) {
if (strlen($word) > $num) {
$resSentence[] = $word;
}
}
$listing_cat[$i] = implode($resSentence);
}
var_dump($listing_cat);
Getting an Undefined Offset error here -- apparently from the $newval array.
Note that the {exp} tag is not PHP, and is simply a sql query by my CMS system which creates the $bags array for me.
<?php
$bags = array();
$newval = array();
$pattern = "[^0-9]";
{exp:query sql="SELECT m_field_id_1 as bags FROM exp_member_data WHERE m_field_id_1 IS NOT NULL"}
$bags[] = "{bags}";
{/exp:query}
foreach ($bags as $key => $value) {
for ( $i = 0, $s = strlen($value); $i < $s; $i++) {
if ( is_numeric($value[$i]) ) {
$newval[$key] .= $value[$i];
}
}
}
$sum = array_sum($newval);
$format = number_format($sum);
echo $format;
?>
Before you can concatenate to a variable, that variable must exist (to avoid a Notice). Simply declare $newval[$key] as an empty string before the for loop:
foreach ($bags as $key => $value) {
$newval[$key] = '';
for ($i = 0, $s = strlen($value); $i < $s; $i++) {
if ( is_numeric($value[$i]) ) {
$newval[$key] .= $value[$i];
}
}
}
By the way, there's nothing wrong with your starting value of $i. It is correct to have it at 0 and not 1 as others are suggesting.
However, if you're trying to remove non-number characters from a string and avoid empty array elements (as your original code does), you can remove the inner for loop and simply:
foreach ($bags as $key => $value) {
$digits = preg_replace('/[^0-9]/', '', $value);
if (strlen($digits)) {
$newval[$key] = $digits;
}
}
As Jrod said you're walking through the characters in $value but you start at 0. strlen() returns the absolute amount of chars in $value so in your for loop you should start at 1 instead of 0.
This is the code you should use:
<?php
$bags = array();
$newval = array();
$pattern = "[^0-9]";
{exp:query sql="SELECT m_field_id_1 as bags FROM exp_member_data WHERE m_field_id_1 IS NOT NULL"}
$bags[] = "{bags}";
{/exp:query}
foreach ($bags as $key => $value) {
$newval[$key] = '';
for ( $i = 1, $s = strlen($value); $i < $s; $i++) {
if ( is_numeric($value[$i]) ) {
$newval[$key] .= $value[$i];
}
}
}
$sum = array_sum($newval);
$format = number_format($sum);
echo $format;
?>
Instead of this
foreach ($bags as $key => $value) {
for ( $i = 0, $s = strlen($value); $i < $s; $i++) {
if ( is_numeric($value[$i]) ) {
$newval[$key] .= $value[$i];
}
}
}
you can write
$newval = preg_replace('~\D+~', '', $bags);
one line is easier to debug than six, isn't it.
I have a PHP array which looks like this example:
$array[0][0] = 'apples';
$array[0][1] = 'pears';
$array[0][2] = 'oranges';
$array[1][0] = 'steve';
$array[1][1] = 'bob';
And I would like to be able to produce from this a table with every possible combination of these, but without repeating any combinations (regardless of their position), so for example this would output
Array 0 Array 1
apples steve
apples bob
pears steve
pears bob
But I would like for this to be able to work with as many different arrays as possible.
this is called "cartesian product", php man page on arrays http://php.net/manual/en/ref.array.php shows some implementations (in comments).
and here's yet another one:
function array_cartesian() {
$_ = func_get_args();
if(count($_) == 0)
return array(array());
$a = array_shift($_);
$c = call_user_func_array(__FUNCTION__, $_);
$r = array();
foreach($a as $v)
foreach($c as $p)
$r[] = array_merge(array($v), $p);
return $r;
}
$cross = array_cartesian(
array('apples', 'pears', 'oranges'),
array('steve', 'bob')
);
print_r($cross);
You are looking for the cartesian product of the arrays, and there's an example on the php arrays site: http://php.net/manual/en/ref.array.php
Syom copied http://www.php.net/manual/en/ref.array.php#54979 but I adapted it this to become an associative version:
function array_cartesian($arrays) {
$result = array();
$keys = array_keys($arrays);
$reverse_keys = array_reverse($keys);
$size = intval(count($arrays) > 0);
foreach ($arrays as $array) {
$size *= count($array);
}
for ($i = 0; $i < $size; $i ++) {
$result[$i] = array();
foreach ($keys as $j) {
$result[$i][$j] = current($arrays[$j]);
}
foreach ($reverse_keys as $j) {
if (next($arrays[$j])) {
break;
}
elseif (isset ($arrays[$j])) {
reset($arrays[$j]);
}
}
}
return $result;
}
I needed to do the same and I tried the previous solutions posted here but could not make them work. I got a sample from this clever guy http://www.php.net/manual/en/ref.array.php#54979. However, his sample did not managed the concept of no repeating combinations. So I included that part. Here is my modified version, hope it helps:
$data = array(
array('apples', 'pears', 'oranges'),
array('steve', 'bob')
);
$res_matrix = $this->array_cartesian_product( $data );
foreach ( $res_matrix as $res_array )
{
foreach ( $res_array as $res )
{
echo $res . " - ";
}
echo "<br/>";
}
function array_cartesian_product( $arrays )
{
$result = array();
$arrays = array_values( $arrays );
$sizeIn = sizeof( $arrays );
$size = $sizeIn > 0 ? 1 : 0;
foreach ($arrays as $array)
$size = $size * sizeof( $array );
$res_index = 0;
for ( $i = 0; $i < $size; $i++ )
{
$is_duplicate = false;
$curr_values = array();
for ( $j = 0; $j < $sizeIn; $j++ )
{
$curr = current( $arrays[$j] );
if ( !in_array( $curr, $curr_values ) )
{
array_push( $curr_values , $curr );
}
else
{
$is_duplicate = true;
break;
}
}
if ( !$is_duplicate )
{
$result[ $res_index ] = $curr_values;
$res_index++;
}
for ( $j = ( $sizeIn -1 ); $j >= 0; $j-- )
{
$next = next( $arrays[ $j ] );
if ( $next )
{
break;
}
elseif ( isset ( $arrays[ $j ] ) )
{
reset( $arrays[ $j ] );
}
}
}
return $result;
}
The result would be something like this:
apples - steve
apples - bob
pears - steve
pears - bob
oranges - steve
oranges - bob
If you the data array is something like this:
$data = array(
array('Amazing', 'Wonderful'),
array('benefit', 'offer', 'reward'),
array('Amazing', 'Wonderful')
);
Then it will print something like this:
Amazing - benefit - Wonderful
Amazing - offer - Wonderful
Amazing - reward - Wonderful
Wonderful - benefit - Amazing
Wonderful - offer - Amazing
Wonderful - reward - Amazing
foreach($parentArray as $value) {
foreach($subArray as $value2) {
$comboArray[] = array($value, $value2);
}
}
Don't judge me..
This works I think - although after writing it I realised it's pretty similar to what others have put, but it does give you an array in the format requested. Sorry for the poor variable naming.
$output = array();
combinations($array, $output);
print_r($output);
function combinations ($array, & $output, $index = 0, $p = array()) {
foreach ( $array[$index] as $i => $name ) {
$copy = $p;
$copy[] = $name;
$subIndex = $index + 1;
if (isset( $array[$subIndex])) {
combinations ($array, $output, $subIndex, $copy);
} else {
foreach ($copy as $index => $name) {
if ( !isset($output[$index])) {
$output[$index] = array();
}
$output[$index][] = $name;
}
}
}
}
#user187291
I modified this to be
function array_cartesian() {
$_ = func_get_args();
if (count($_) == 0)
return array();
$a = array_shift($_);
if (count($_) == 0)
$c = array(array());
else
$c = call_user_func_array(__FUNCTION__, $_);
$r = array();
foreach($a as $v)
foreach($c as $p)
$r[] = array_merge(array($v), $p);
return $r;
}
so it returns that all-important empty array (the same result as no combinations) when you pass 0 arguments.
Only noticed this because I'm using it like
$combos = call_user_func_array('array_cartesian', $array_of_arrays);
function array_comb($arrays)
{
$result = array();
$arrays = array_values($arrays);
$sizeIn = sizeof($arrays);
$size = $sizeIn > 0 ? 1 : 0;
foreach ($arrays as $array)
$size = $size * sizeof($array);
for ($i = 0; $i < $size; $i ++)
{
$result[$i] = array();
for ($j = 0; $j < $sizeIn; $j ++)
array_push($result[$i], current($arrays[$j]));
for ($j = ($sizeIn -1); $j >= 0; $j --)
{
if (next($arrays[$j]))
break;
elseif (isset ($arrays[$j]))
reset($arrays[$j]);
}
}
return $result;
}
I had to make combinations from product options. This solution uses recursion and works with 2D array:
function options_combinations($options) {
$result = array();
if (count($options) <= 1) {
$option = array_shift($options);
foreach ($option as $value) {
$result[] = array($value);
}
} else {
$option = array_shift($options);
$next_option = options_combinations($options);
foreach ($next_option as $next_value) {
foreach ($option as $value) {
$result[] = array_merge($next_value, array($value));
}
}
}
return $result;
}
$options = [[1,2],[3,4,5],[6,7,8,9]];
$c = options_combinations($options);
foreach ($c as $combination) {
echo implode(' ', $combination)."\n";
}
Elegant implementation based on native Python function itertools.product
function direct_product(array ...$arrays)
{
$result = [[]];
foreach ($arrays as $array) {
$tmp = [];
foreach ($result as $x) {
foreach ($array as $y) {
$tmp[] = array_merge($x, [$y]);
}
}
$result = $tmp;
}
return $result;
}