How do you find most common array in multidimensional array using PHP - php

I need to find the most common (most occurring) array in a multidimensional array. Not the most common values like this post - Find Common most values in multidimensional array in PHP - but rather the most common combination.
For example, if I have the following:
$a1=array(
array('704322062'),
array('678073776', '704322062'),
array('678073776', '704322062'),
array('704322064'),
array('704322062'),
array('678073776'),
array('678073776', '704322062')
);
I want to be able to detect that the array that occurs most often is array('678073776', '704322062') not that the string '704322062' is most common.
I've tried using array_intersect but couldn't get it working for this scenario.
Thanks!

array_count_values only works with scalar values, not when the items are arrays themselves. But we can still use that function, if we transform your arrays into strings first - by encoding them as JSON.
// fill temp array with items encoded as JSON
$temp = [];
foreach($a1 as $item) {
$temp[] = json_encode($item);
}
// count how many times each of those values occurs
$value_counts = array_count_values($temp);
// sort by number of occurrence, while preserving the keys
ksort($value_counts);
// pick the first key from the temp array
$first = array_key_first($value_counts);
This will get you ["678073776","704322062"] in $first now - you can json_decode it again, if you want your “original” array.
Note that this does not take into account, that two arrays could occur the same amount of times - then it will just pick the “random” first one of those. If you need to handle that case as well somehow, then you can determine the maximum value in $temp first, and then filter it by that value, so that only those keys of the corresponding arrays will be left.

Related

php function sometimes pushing arrays other times objects

I have an app which i'm making a HTTP request via PHP to retrieve some XML data. I'm then taking a string in that data, splitting it by spaces (" ") and pushing it into a new array. I'm then taking an existing array and de-duping it against this new array using the function array_diff. Here is my code below:
// THIS ARRAY IS MUCH LONGER BUT HAVE JUST PUT IN A FEW WORDS
$stopwords = array("a", "about", "above", "above", "across", "after", "afterwards", "again");
// this is my XML call
$test = simplexml_load_file('https://some-xml-endpoint.com/endpoint');
// defining a blank array where I want the result to go
$mappedWordsObj = [];
for($i = 0;$i < count($test->data);$i++) {
// if I echo this it returns me a string with no quotes (sometimes the quotes would be in there and I thought this may have been the issue)
$comment = chop(strtolower($test->data[$i]->comments));
// here I split the comment into an array by spaces
$wordsArray = explode(' ', $comment);
//here I compare my new array of words with the stopwords I want removed from the wordsArray
$arr_1 = array_diff($wordsArray, $stopwords);
// here I push into the $mappedWordsObj array
array_push($mappedWordsObj, $arr_1);
}
// here I push to the DOM the result to see how my array looks
echo json_encode($mappedWordsObj);
My issue is that in the resulting $mappedWordsObj array, I expect all the array items to be arrays themselves that contain the words but some of the items are getting inserted in the $mappedWordsObj as arrays with the words and others as objects with properties whos values are the words. Here is a snippet of the data returned:
{"0":"i","1":"just","2":"want","4":"switch","6":"existing","7":"t-mobile","8":"pay","13":"ee","14":"pay","15":"monthly.","16":"i","17":"don't","18":"want","20":"new","21":"phone!","23":"page","24":"does","26":"tell","31":"this!"},{"0":"just","2":"option","4":"'sim","5":"only'","9":"'radio","10":"button'","11":"forced","12":"selection."},
["voice","recignition"],
["testing","ol"],
{"0":"can't","1":"think","4":"i","7":"simple","9":"easy"},{"2":"instead","3":"lol"},
["n\/a"],
["great","website"],
I'd like to just have an array of arrays so can anyone please tell me where i've gone wrong?
Cheers
When you use json_encode, it will convert PHP arrays to either JSON arrays or JSON objects. Which one is output depends completely on the array keys in the PHP array. For PHP arrays with sequential, numeric indexes starting at 0, the JSON output will be an array. For PHP arrays with any other indexes, the JSON output will be an object.
The array_diff produces an array where the indexes are not sequential in some cases. You can use array_values to reindex the result before appending it to your output array.
array_push($mappedWordsObj, array_values($arr_1));
Side note - array_push actually isn't necessary here. You can use
$mappedWordsObj[] = array_values($arr_1);
The array_push documentation actually recommends doing it this way when you're only appending one item to the array. But, it's a pretty small optimization, so if array_push looks better to you, never mind. :)

Can't flatten multidimensional array with lots of duplicates

I'm trying to create a script that, based on an input a?? creates an array of all the combinations and permutations of all words containing an a and two other characters from the alphabet.
Values are such as a, ab, ba, dab, bga etc - as you may see the array contains (or should contain) a weird amount of values.
The problem is that the functions I use in the script outputs even more values with many duplicates.
And for some reason I can not create a flattened array without duplicates. I tried to use array_unique() but it doesn't work here. I tried to use explode() and implode() to flatten the result array, but no success. Even if I succeed to create a string from the values, when I try to transform this string into an array, the result is again the actual multi-dimensional array.
This drives me crazy, and as you see the code, I'm a beginner in PHP.
Any help to transform the actual multidimensional array to a flattened one without duplicates is highly appreciated. An example: actually the array contains 12168 sub-arrays, and only the string a occurs 1456 times. What I need is an array that doesn't have sub-arrays and contains each results only one time.
The PHP code is available at here
and the output is here:
Have you tried something like:
$inputString = 'a??';
$array = array();
if (strpos($inputString, 'a') !== false && !in_array($inputString, $array)) {
$array[] = $inputString;
}
echo '<pre>'; print_r($array); echo '</pre>';

when selecting random values from arrays, make sure two certain ones do not appear next to each other

I have an array with 18 values in it from which I select random values using $array[rand(0,17)]. I put these randomly selected values next to each other on the page. Within the array are 6 sets of values that I do not want to be put next to each other on the page. Is there any way that I can detect when the pairs are together and select new values because of that
warning: Do you know for sure that you won't get any degenerate cases where there are no possible orderings of the array? For example, if you won't allow the pairs [1,2] or [2,1] and the array you get is [1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2], the you're out of luck. There's no way to display the array in the way you want, and a method like I describe below will never terminate.
I would use shuffle($array) and then iterate through the shuffled array one item at a time, to find out whether any value is "incompatible" with the item before it. If so, just reshuffle the array and try again. You can't predict how many tries it will take to get a shuffled array that works, but the amount of time it takes should be negligible.
To detect whether two values are compatible, I'd suggest making an array that contains all incompatible pairs. For example, if you don't want to have the consecutive pairs 1 and 3 or 2 and 5, then your array would be:
$incompatible = array(
array(1,3),
array(2,5) );
Then you'd iterate over your shuffled array with something like:
for ($i=1; i<count($array)-1; i++;) {
$pair = $array[i, i+1]; // this is why the for loop only goes to the next-to-last item
if in_array($pair, $incompatible) {
// you had an incompatible pair in your shuffled array.
// break out of the for loop, re-sort your array, and try again.
}
}
// if you get here, there were no incompatible pairs
// so go ahead and print the shuffled array!
Or use with unset() for remove the keys, or use by Session, for next skip.

Get arbitrary number of random elements from a php array in one line

I wanted to pull an arbitrary number of random elements from an array in php. I see that the array_rand() function pulls an arbitrary number of random keys from an array. All the examples I found online showed then using a key reference to get the actual values from the array, e.g.
$random_elements = array();
$random_keys = array_rand($source_array);
foreach ( $random_keys as $random_key ) {
$random_elements[] = $source_array[$random_key];
}
That seemed cumbersome to me; I was thinking I could do it more concisely. I would need either a function that plain-out returned random elements, instead of keys, or one that could convert keys to elements, so I could do something like this:
$random_elements = keys_to_elements(array_rand($source_array, $number, $source_array));
But I didn't find any such function(s) in the manual nor in googling. Am I overlooking the obvious?
What about usung array_flip? Just came to my mind:
$random_elements = array_rand(array_flip($source_array), 3);
First we flip the array making its values become keys, and then use array_rand.
An alternate solution would be to shuffle the array and return a slice from the start of it.
Or, if you don't want to alter the array, you could do:
array_intersect_key($source_array, array_combine(
array_rand($source_array, $number), range(1, $number)));
This is a bit hacky because array_intersect can work on keys or values, but not selecting keys from one array that match values in another. So, I need to use array_combine to turn those values into keys of another array.
You could do something like this, not tested!!!
array_walk(array_rand($array, 2), create_function('&$value,$key',
'$value = '.$array[$value].';'));

Alternative to array_shift function

Ok, I need keys to be preserved within this array and I just want to shift the 1st element from this array. Actually I know that the first key of this array will always be 1 when I do this:
// Sort it by 1st group and 1st layout.
ksort($disabled_sections);
foreach($disabled_sections as &$grouplayout)
ksort($grouplayout);
Basically I'd rather not have to ksort it in order to grab this array where the key = 1. And, honestly, I'm not a big fan of array_shift, it just takes to long IMO. Is there another way. Perhaps a way to extract the entire array where $disabled_sections[1] is found without having to do a foreach and sorting it, and array_shift. I just wanna add $disabled[1] to a different array and remove it from this array altogether. While keeping both arrays keys structured the way they are. Technically, it would even be fine to do this:
$array = array();
$array = $disabled_sections[1];
But it needs to remove it from $disabled_sections. Can I use something like this approach...
$array = array();
$array = $disabled_sections[1];
$disabled_sections -= $disabled_sections[1];
Is something like the above even possible??
Thanks.
Despite there being an accepted answer to this; in case someone else stumbles across this, a way to unset the first element of an array (regardless of its key, or the order of its keys) without using array_shift is:
reset($array); // sets internal array pointer to start
unset($array[key($array)]); // key() returns key of current array element
Though I'm fairly convinced that's what array_shift does internally (so I imagine there would be no performance gain to this), excepting an additional return of the value retrieved:
$element = reset($array); // also returns element
unset($array[key($array)]);
return $element;
Just for completion's sake.
While there's no -= operator in that fashion, you can use unset to remove that element from an array:
unset(disabled_sections[1]);
But that's just implementing your own version of shift. I do wonder under what situation you're finding array_shift() to be 'slow' and how you're testing said slowness.
Numeric arrays are sorted numerical by default - no ksort is required. Maybe you should try something like
while($array = array_shift($group_of_arrays)) {
// ... do stuff
}
If you are not concerned about the order in which you pull elements out of the array, you can use "array_pop" instead of "array_shift". Since "array_pop" takes the elements off of the end of the array, no reindexing is required and performance increases dramatically. In testing with an array of about 80,000 entries I am seeing about a 90% decrease in processing time with "array_pop".

Categories