PHP Sorting Multidimensional Array Sorted by Weight - php

I just asked this question a moment ago but I asked incorrectly so I apologize.
I'm hoping there's an easy way to do this without tons and tons of loops.
I have a matrix in the following manner:
Foo1 Foo2 Foo3 .... FooN
Jan 1 8 5 4
Feb 10 12 15 11
Mar 12 7 4 3
Apr 10 16 7 17
Assuming the following array:
$arrayMonths = array(
'jan' => array(1, 8, 5,4)
'feb' => array(10,12,15,11)
'mar' => array(12, 7, 4, 3)
'apr' => array(10,16,7,17)
);
I need to sort the above array and show it in the following manner:
array[apr][FooN] = 17
array[feb][Foo3] = 15
array[mar][Foo1] = 12
array[jan][Foo2] = 8
Essentially, I need to get the greatest sum of the above weights, one month can only have one foo and one foo can only have one month. In the above example, the result would be 52.
Thanks

See Demo : http://codepad.org/vDI2k4n6
$arrayMonths = array(
'jan' => array(1, 8, 5,4),
'feb' => array(10,12,15,11),
'mar' => array(12, 7, 4, 3),
'apr' => array(10,16,7,17),
);
$position = array("Foo1","Foo2","Foo3","FooN");
$set = array();
foreach($arrayMonths as $key => $value)
{
$max = max($value);
$pos = array_search($max, $value);
$set[$key][$position[$pos]] = $max ;
}
function cmp($a, $b)
{
foreach($a as $key => $value )
{
foreach ($b as $bKey => $bValue)
{
return $bValue - $value ;
}
}
}
uasort($set,"cmp");
var_dump($set);
Output
array
'apr' =>
array
'FooN' => int 17
'feb' =>
array
'Foo3' => int 15
'mar' =>
array
'Foo1' => int 12
'jan' =>
array
'Foo2' => int 8

$totalArr = array();
$total = 0;
foreach($arrayMonths as $month => $row)
{
$high = max($row);
$totalArr[$month]['foo'] = $high;
$total += $high;
}
echo "Total is: " . $total . "\n\n";
print_r($totalArr);
Outputs:
Total is: 52
Array
(
[jan] => Array
(
[foo] => 8
)
[feb] => Array
(
[foo] => 15
)
[mar] => Array
(
[foo] => 12
)
[apr] => Array
(
[foo] => 17
)
)
Use uasort() if you want to sort the new array.
http://php.net/manual/en/function.uasort.php

The PHP function max() is the key here:
$sum = 0;
foreach ($array as $row) {
$sum += max($row);
}
echo $sum;

Look into this way of doing it.
http://www.php.net/manual/en/function.uasort.php
Input the array and a reference to a comparison function that you write yourself.

$arr_new = array();
foreach(array_keys($arrayMonths) as $h) {
$int_max = max($arrayMonths[$h]);
foreach(array_keys($arrMonths[$h]) as $h2)
if ($arrMonths[$h][$h2] == $int_max) {
$arr_new[$h]["foo{$h2}"] = $int_max;
break;
}
}

Related

I want to make a key value pair of numeric array in PHP on the base of index

foreach($manualsArray as $manuls){
for($i=0;$i<=count($manuls);$i++){
if($i/2 == 0){
$manuls = 23;
print($manuls);
}
else{
$manualsArray= 98;
print($manualsArray);
}
print($manualsArray);
}
}
I want to create key value pairs according to index like 0 is key 1 is value 2 is key 3 is value and so on.
the sample input is write below
Array
(
[0] => Array
(
[0] => Faucet Centers
[1] => 6, 4, 13, 12, 7, 10, 14, 16, 8, 5, 9, 15, 11 in.
[2] => Flow Rate (GPM)
[3] => 1.2
[4] => Height
[5] => 5.875 in.
[6] => Max Deck Thickness
[7] => 2.25 in.
[8] => Spout Height
[9] => 3.625 in.
[10] => Spout Reach
[11] => 5 in.
)
)
You can achieve this by changing your loop to increment by 2 each time and take $i as the key and $i+1 as the value...
$output = [];
foreach($manualsArray as $manual){
$m = [];
for ( $i = 0; $i < count($manual); $i+=2 ) {
$m [$manual[$i]] = $manual[$i+1];
}
$output [] = $m;
}
print_r($output);
you can use array_chunk()
foreach($manualsArray as $manuls){
foreach( array_chunk($manuls, 2) as $pair) {
echo 'key: ' . $pair[0] . ' is value: '. $pair[1] . "<br>/n";
}
}
or if you want an associative array
$result_array = [];
foreach($manualsArray as $manuls){
foreach( array_chunk($manuls, 2) as $pair) {
$result_array[] = [$pair[0] => $pair[1]];
}
}
var_export($result_array);
https://www.php.net/manual/en/function.array-chunk.php
Use modulo for that:
<?php
$newarray = array();
foreach($yourarray[0] as $id => $val){
if($id % 2 == 0){
$last_index = $val;
}else{
$newarray[$last_index] = $val;
}
}
?>
I assume that your array is the one you have given, so it's 2-dimensional.
If not, use $yourarray instead of $yourarray[0].

Find combination of array keys with values

In order to optimize the output I recently ran into a situation where I have to get the all the combinations of array keys inside an array. I looked into several places (including StackOverflow) but could not find the solution since most are related to permutation rather than combination.
Given this input
$input = ['jack' => 11, 'moe' => 12, 'shane' => 12];
Output should be something like this (the order inside an array does not matter).
$output = [
['jack' => 11],
['jack' => 11, 'moe' => 12]
['jack' => 11, 'moe' => 12, 'shane' => 12]
['moe' => 12],
['moe' => 12, 'shane' => 12]
['shane' => 12],
['shane' => 12, 'jack' => 11]
];
I tried this but after third iteration it does not work.
function combination(array $inputs, array $temp, &$collect) {
if (!empty($temp)) {
$collect[] = $temp;
}
for ($i = 0; $i < sizeof($inputs); $i++) {
$inputCopy = $inputs;
$elem = array_splice($inputCopy, $i, 1);
if (count($inputCopy) > 0) {
$temp[array_keys($elem)[0]] = array_values($elem)[0];
combination($inputCopy, $temp, $collect);
} else {
$temp[array_keys($elem)[0]] = array_values($elem)[0];
$collect[] = $temp;
$temp = [];
}
$i++;
}
}
Though I need this in PHP even Python (without using itertools combination), Java, Javascript will work for me.
I have found a way of doing what you want, but definitely, this is not a "fancy" solution. I would suggest you to work a little bit with it to find something better, but at least this gives you the result.
Here you go :
<?php
$baseArray = [
"joe" => 11,
"molly" => 12,
"sam" => 13,
];
function getAllPermutations($array = []) {
if (empty($array)) {
return [];
}
$result = [];
foreach ($array as $key => $value) {
unset($array[$key]);
$subPermutations = getAllPermutations($array);
$result[] = [$key => $value];
foreach ($subPermutations as $sub) {
$result[] = array_merge([$key => $value] , $sub);
}
}
return $result;
}
print_r(getAllPermutations($baseArray));
Output being :
Array
(
[0] => Array
(
[joe] => 11
)
[1] => Array
(
[joe] => 11
[molly] => 12
)
[2] => Array
(
[joe] => 11
[molly] => 12
[sam] => 13
)
[3] => Array
(
[joe] => 11
[sam] => 13
)
[4] => Array
(
[molly] => 12
)
[5] => Array
(
[molly] => 12
[sam] => 13
)
[6] => Array
(
[sam] => 13
)
) }
Hope this helped.
You read about really clever non-recursive algorithm here: PHP: Find every combination of an Array. You can adopt it (mostly copy and paste) to write generator function:
function keyCombinations($array)
{
$keys = array_keys($array);
$num = count($keys);
$total = pow(2, $num);
for ($i = 1; $i < $total; $i++) {
$combination = [];
for ($j = 0; $j < $num; $j++) {
if (pow(2, $j) & $i) {
$key = $keys[$j];
$combination[$key] = $array[$key];
}
}
yield $combination;
}
}
One important point here. In the original article $i initialized with 0, we initialize it with 1 to exclude empty array from the result.
Having this function you can get all combinations:
foreach (keyCombinations($input) as $combination) {
print_r($combination);
}
Here is working demo.
If, in your final combination, you include the empty set, your problem is equivalent to enumerating a binary number of "n" bits. Where "n" is the number of elements in your set.
You need a recursive algorithm like this one:
def comb(initialSet, results=[], currentIndex=0, currentResult=[]):
if currentIndex >= len(initialSet):
results.append( currentResult[:] )
else:
currentResult.append( initialSet[currentIndex] )
comb(initialSet, results, currentIndex + 1, currentResult)
currentResult.pop()
comb(initialSet, results, currentIndex + 1, currentResult)
return results

Getting specidic values from PHP arrays

Is there a way to get the first value from array, then the first value key + 3 ; then +6 then + 9 ans so on
Take this array for example,
array(1,2,5,14,19,2,11,3,141,199,52,24,16)
i want extract a value every 3 so the result would be
array(1,14,11,199,16)
Can i do that with existing PHP array function?
Use a for loop and increment the counter variable by 3.
for ($i = 0; $i <= count(your array); $i+3) {
echo $myarray[i]
}
The following is function that will handle extracting the values from a given array. You can specify the number of steps between each value and if the results should use the same keys as the original. This should work with regular and associative arrays.
<?php
function extractValues($array, $stepBy, $preserveKeys = false)
{
$results = array();
$index = 0;
foreach ($array as $key => $value) {
if ($index++ % $stepBy === 0) {
$results[$key] = $value;
}
}
return $preserveKeys ? $results : array_values($results);
}
$array = array(1, 2, 5, 14, 19, 2, 11, 3, 141, 199, 52, 24, 16);
$assocArray = array('a' => 1, 'b' => 2, 'c' => 5, 'd' => 14, 'e' => 19, 'f' => 2, 11, 3, 141, 199, 52, 24, 16);
print_r(extractValues($array, 3));
print_r(extractValues($array, 3, true));
print_r(extractValues($assocArray, 5));
print_r(extractValues($assocArray, 5, true));
?>
Output
Array
(
[0] => 1
[1] => 14
[2] => 11
[3] => 199
[4] => 16
)
Array
(
[0] => 1
[3] => 14
[6] => 11
[9] => 199
[12] => 16
)
Array
(
[0] => 1
[1] => 2
[2] => 52
)
Array
(
[a] => 1
[f] => 2
[4] => 52
)
Use a loop and check the key.
$result = array();
foreach($array as $key => $value) {
if ($key % 3 === 0) {
$result[] = $value;
}
}
Try below one:
<?php
$your_array = array (1,2,5,14,19,2,11,3,141,199,52,24,16);
$every_3 = array();
$i = 0;
foreach($your_value as $value) {
$i++;
if($i%3==0){
$every_3[]=$value;
}
}
var_dump($every_3);
?>
Do like this
$arr=array (1,2,5,14,19,2,11,3,141,199,52,24,16);
$narr=array();
for($i=0;$i<count($arr);$i=$i+3){
$narr[]=$arr[$i]
}
print_r($narr);
<?php
$mynums = array(1,2,5,14,19,2,11,3,141,199,52,24,16);
foreach ($mynums as $key => $value) {
if ( $key % 3 === 0)
{
$newnum[] = $value;
}
}
var_dump($newnum);
?>
$data = array(1,2,5,14,19,2,11,3,141,199,52,24,16);
$matches = array();
foreach($data as $key => $value)
{
if($key%3 === 0)
{
$matches[] = $value;
}
}
var_dump($matches);
The only way you could do it would be to use a loop, count the length of an array, and loop through using a % mathmatical operator.
It gives you a remainder of a division: http://au2.php.net/operators.arithmetic

PHP Find All (somewhat) Unique Combinations of an Array

I've been looking at PHP array permutation / combination questions all day.. and still can't figure it out :/
If I have an array like:
20 //key being 0
20 //key being 1
22 //key being 2
24 //key being 3
I need combinations like:
20, 20, 22 //keys being 0 1 2
20, 20, 24 //keys being 0 1 3
20, 22, 24 //keys being 0 2 3
20, 22, 24 //keys being 1 2 3
The code I currently have gives me:
20, 22, 24
because it doesn't want to repeat 20... but that's what I need!
Here is the code I have. it is directly from Php recursion to get all possibilities of strings
function getCombinations($base,$n){
$baselen = count($base);
if($baselen == 0){
return;
}
if($n == 1){
$return = array();
foreach($base as $b){
$return[] = array($b);
}
return $return;
}else{
//get one level lower combinations
$oneLevelLower = getCombinations($base,$n-1);
//for every one level lower combinations add one element to them that the last element of a combination is preceeded by the element which follows it in base array if there is none, does not add
$newCombs = array();
foreach($oneLevelLower as $oll){
$lastEl = $oll[$n-2];
$found = false;
foreach($base as $key => $b){
if($b == $lastEl){
$found = true;
continue;
//last element found
}
if($found == true){
//add to combinations with last element
if($key < $baselen){
$tmp = $oll;
$newCombination = array_slice($tmp,0);
$newCombination[]=$b;
$newCombs[] = array_slice($newCombination,0);
}
}
}
}
}
return $newCombs;
}
I've been playing around with the ($b == $lastEl) line, with no luck
===============
Questions I've already looked at, and are not the same OR that created an out of memory error!:
How can I get all permutations in PHP without sequential duplicates?
Permutations - all possible sets of numbers
Combinations, Dispositions and Permutations in PHP
PHP array combinations
Get all permutations of a PHP array?
PHP: How to get all possible combinations of 1D array?
Select only unique array values from this array
Get all permutations of a PHP array?
PHP: How to get all possible combinations of 1D array?
Select only unique array values from this array
How can I get all permutations in PHP without sequential duplicates?
Algorithm to return all combinations of k elements from n
Find combination(s) sum of element(s) in array whose sum equal to a given number
Combinations, Dispositions and Permutations in PHP
PHP array combinations
Php recursion to get all possibilities of strings
How to return permutations of an array in PHP?
Permutations - all possible sets of numbers
Subset-sum problem in PHP with MySQL
Find unique combinations of values from arrays filtering out any duplicate pairs
Finding all the unique permutations of a string without generating duplicates
Generate all unique permutations
Subset sum for exactly k integers?
I've tried some of these algorithms with an array of 12 items, and end up running out of memory. However the algorithm that I'm currently using doesn't give me an out of memory error.... BUT.. I need those duplicates!
If you don't mind using a couple of global variables, you could do this in PHP (translated from a version in JavaScript):
<?PHP
$result = array();
$combination = array();
function combinations(array $myArray, $choose) {
global $result, $combination;
$n = count($myArray);
function inner ($start, $choose_, $arr, $n) {
global $result, $combination;
if ($choose_ == 0) array_push($result,$combination);
else for ($i = $start; $i <= $n - $choose_; ++$i) {
array_push($combination, $arr[$i]);
inner($i + 1, $choose_ - 1, $arr, $n);
array_pop($combination);
}
}
inner(0, $choose, $myArray, $n);
return $result;
}
print_r(combinations(array(20,20,22,24), 3));
?>
OUTPUT:
Array ( [0] => Array ( [0] => 20
[1] => 20
[2] => 22 )
[1] => Array ( [0] => 20
[1] => 20
[2] => 24 )
[2] => Array ( [0] => 20
[1] => 22
[2] => 24 )
[3] => Array ( [0] => 20
[1] => 22
[2] => 24 ) )
The pear package Math_Combinatorics makes this kind of problem fairly easy. It takes relatively little code, it's simple and straightforward, and it's pretty easy to read.
$ cat code/php/test.php
<?php
$input = array(20, 20, 22, 24);
require_once 'Math/Combinatorics.php';
$c = new Math_Combinatorics;
$combinations = $c->combinations($input, 3);
for ($i = 0; $i < count($combinations); $i++) {
$vals = array_values($combinations[$i]);
$s = implode($vals, ", ");
print $s . "\n";
}
?>
$ php code/php/test.php
20, 20, 22
20, 20, 24
20, 22, 24
20, 22, 24
If I had to package this as a function, I'd do something like this.
function combinations($arr, $num_at_a_time)
{
include_once 'Math/Combinatorics.php';
if (count($arr) < $num_at_a_time) {
$arr_count = count($arr);
trigger_error(
"Cannot take $arr_count elements $num_at_a_time "
."at a time.", E_USER_ERROR
);
}
$c = new Math_Combinatorics;
$combinations = $c->combinations($arr, $num_at_a_time);
$return = array();
for ($i = 0; $i < count($combinations); $i++) {
$values = array_values($combinations[$i]);
$return[$i] = $values;
}
return $return;
}
That will return an array of arrays. To get the text . . .
<?php
include_once('combinations.php');
$input = array(20, 20, 22, 24);
$output = combinations($input, 3);
foreach ($output as $row) {
print implode($row, ", ").PHP_EOL;
}
?>
20, 20, 22
20, 20, 24
20, 22, 24
20, 22, 24
Why not just use binary? At least then its simple and very easy to understand what each line of code does like this? Here's a function i wrote for myself in a project which i think is pretty neat!
function search_get_combos($array){
$bits = count($array); //bits of binary number equal to number of words in query;
//Convert decimal number to binary with set number of bits, and split into array
$dec = 1;
$binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
while($dec < pow(2, $bits)) {
//Each 'word' is linked to a bit of the binary number.
//Whenever the bit is '1' its added to the current term.
$curterm = "";
$i = 0;
while($i < ($bits)){
if($binary[$i] == 1) {
$curterm[] = $array[$i]." ";
}
$i++;
}
$terms[] = $curterm;
//Count up by 1
$dec++;
$binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
}
return $terms;
}
For your example, this outputs:
Array
(
[0] => Array
(
[0] => 24
)
[1] => Array
(
[0] => 22
)
[2] => Array
(
[0] => 22
[1] => 24
)
[3] => Array
(
[0] => 20
)
[4] => Array
(
[0] => 20
[1] => 24
)
[5] => Array
(
[0] => 20
[1] => 22
)
[6] => Array
(
[0] => 20
[1] => 22
[2] => 24
)
[7] => Array
(
[0] => 20
)
[8] => Array
(
[0] => 20
[1] => 24
)
[9] => Array
(
[0] => 20
[1] => 22
)
[10] => Array
(
[0] => 20
[1] => 22
[2] => 24
)
[11] => Array
(
[0] => 20
[1] => 20
)
[12] => Array
(
[0] => 20
[1] => 20
[2] => 24
)
[13] => Array
(
[0] => 20
[1] => 20
[2] => 22
)
[14] => Array
(
[0] => 20
[1] => 20
[2] => 22
[3] => 24
)
)
Had the same problem and found a different and bitwise, faster solution:
function bitprint($u) {
$s = array();
for ($n=0; $u; $n++, $u >>= 1){
if ($u&1){
$s [] = $n;
}
}
return $s;
}
function bitcount($u) {
for ($n=0; $u; $n++, $u = $u&($u-1));
return $n;
}
function comb($c,$n) {
$s = array();
for ($u=0; $u<1<<$n; $u++){
if (bitcount($u) == $c){
$s [] = bitprint($u);
}
}
return $s;
}
This one generates all size m combinations of the integers from 0 to n-1, so for example
m = 2, n = 3 and calling comb(2, 3) will produce:
0 1
0 2
1 2
It gives you index positions, so it's easy to point to array elements by index.
Edit: Fails with input comb(30, 5). Have no idea why, anyone any idea?
Cleaned up Adi Bradfield's sugestion using strrev and for/foreach loops, and only get unique results.
function search_get_combos($array = array()) {
sort($array);
$terms = array();
for ($dec = 1; $dec < pow(2, count($array)); $dec++) {
$curterm = array();
foreach (str_split(strrev(decbin($dec))) as $i => $bit) {
if ($bit) {
$curterm[] = $array[$i];
}
}
if (!in_array($curterm, $terms)) {
$terms[] = $curterm;
}
}
return $terms;
}
The Idea is simple. Suppose you know how to permute, then if you save these permutations in a set it becomes a combinations. Set by definition takes care of the duplicate values. The Php euqivalent of Set or HashSet is SplObjectStorage and ArrayList is Array. It should not be hard to rewrite. I have an implementation in Java:
public static HashSet<ArrayList<Integer>> permuteWithoutDuplicate(ArrayList<Integer> input){
if(input.size()==1){
HashSet<ArrayList<Integer>> b=new HashSet<ArrayList<Integer>>();
b.add(input);
return b;
}
HashSet<ArrayList<Integer>>ret= new HashSet<ArrayList<Integer>>();
int len=input.size();
for(int i=0;i<len;i++){
Integer a = input.remove(i);
HashSet<ArrayList<Integer>>temp=permuteWithoutDuplicate(new ArrayList<Integer>(input));
for(ArrayList<Integer> t:temp)
t.add(a);
ret.addAll(temp);
input.add(i, a);
}
return ret;
}

PHP Need to recursively reverse an array

I need to recursively reverse a HUGE array that has many levels of sub arrays, and I need to preserve all of the keys (which some are int keys, and some are string keys), can someone please help me? Perhaps an example using array_reverse somehow? Also, is using array_reverse the only/best method of doing this?
Thanks :)
Try this:
function array_reverse_recursive($arr) {
foreach ($arr as $key => $val) {
if (is_array($val))
$arr[$key] = array_reverse_recursive($val);
}
return array_reverse($arr);
}
Recursively:
<?php
$a = array(1,3,5,7,9);
print_r($a);
function rev($a) {
if (count($a) == 1)
return $a;
return array_merge(rev(array_slice($a, 1, count($a) - 1)), array_slice($a, 0, 1));
}
$a = rev($a);
print_r($a);
?>
output:
Array
(
[0] => 1
[1] => 3
[2] => 5
[3] => 7
[4] => 9
)
Array
(
[0] => 9
[1] => 7
[2] => 5
[3] => 3
[4] => 1
)
Reversing a HUGE php array in situ (but not recursively):
function arrayReverse(&$arr){
if (!is_array($arr) || empty($arr)) {
return;
}
$rev = array();
while ( false !== ( $val = end($arr) ) ){
$rev[ key($arr) ] = $val;
unset( $arr[ key($arr) ] );
}
$arr = $rev;
}
//usage
$test = array(5, 'c'=>100, 10, 15, 20);
arrayReverse($test);
var_export($test);
// result: array ( 3 => 20, 2 => 15, 1 => 10, 'c' => 100, 0 => 5, )

Categories