Getting separate different value in an array - php

I have this kind of problem that I can't get the same value in an array and separate the different value inside an array
I have done using for loop but it seems like my logic wasn't correct.
Value of $supplier_id is
Array (
[0] => 82
[1] => 82
[2] => 96
[3] => 96
[4] => 28
)
for($x = 0; $x < count($supplier_id); $x++){
for($i = 0; $i < count($supplier_id); $i++){
if($supplier_id[$x] == $supplier_id[$i]){
$same_supp[$x]['same_supp'] = $supplier_id[$x];
}else{
}
}
}
I want to store the values inside the array with the same value and separate the different value.
My expected output is
$same_supp[0] = array(0 => 82, 1 => 82);
$same_supp[1] = array(0 => 96, 1 => 96);
and separate the different value which is 28 and store it in different variable.

Group them, filter out the single occurrences, and remove the temporary keys.
Code: (Demo)
$array = [82, 82, 96, 96, 28];
foreach ($array as $v) {
$temp[$v][] = $v;
}
foreach ($temp as $a) {
if (count($a) != 1) {
$result[] = $a;
}
}
var_export($result);
Output:
array (
0 =>
array (
0 => 82,
1 => 82,
),
1 =>
array (
0 => 96,
1 => 96,
),
)

Since the inner loop ($i) also run on the same iteration as the outer loop ($x), it will not only find the duplicates, but also all of the elements.
You can fix it by skipping the check of the same item (when $i and $x are equal)
for($x = 0; $x < count($supplier_id); $x++){
for($i = 0; $i < count($supplier_id); $i++){
if ($x == $i) continue;
...
...

Related

How to merge two array in mysql query

From MySQL join query I got result like:
Array ( [0] => c1 [1] => ot1 [2] => ot1 [3] => R )
Array ( [0] => 20 [1] => 10 [2] => 15 [3] => 5 )
But I want result like:
c1 = [20]
ot1 = [10,15]
R = [5]
Please help me.
Assuming
$array1 = array( 0 => 'c1', 1 => 'ot1', 2 => 'ot1' 3 => 'R' )
$array2 = array( 0 => 20, 1 => 10, 2 => 15, 3 => 5 )
Try this:
for($i = 0; $i < count($array1); $i++){
if(!isset(${$array1[$i]}))
${$array1[$i]} = [];
${$array1[$i]}[] = $array2[$i];
}
Note that this works only when keys are continous integers starting from 0 and both arrays have the same dimension
Assuming the first array is called $array1 and the other is called $array2 try this:
$merged = []; //new array for merged values
foreach ($array1 as $key => $value) { //iterate over the array which holds keys
if (!isset($merged[$value])) { //if a key does not exist in new array yet
$merged[$value] = []; //add it
}
$merged[$value][] = $array2[$key]; //add new value from the other array under this key
}
as long as the integrity of your arrays is preserved, there are no restrictions about continuous keys like in the other answer
Use this one
$array1 = array('c1', 'ot1', 'ot1', 'R');
$array2 = array(20, 10, 15, 5);
$array3 = array();
for ($i = 0; $i < count($array1); $i++) {
if (array_key_exists($array1[$i], $array3)) {
$array3[$array1[$i]] = array($array3[$array1[$i]], $array2[$i]);
} else {
$array3[$array1[$i]] = $array2[$i];
}
}

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

Numeric array: add value of previous element to current element

For each element in the array, I need to add value of previous element to it's current element. Example:
Array
(
[0] => 460
[1] => 25
[2] => 25
[3] => 25
[4] => 25
[5] => 25
[6] => 25
)
How can I get like following:
Array
(
[0] => 460
[1] => 485
[2] => 510
[3] => 535
[4] => 560
[5] => 585
[6] => 610
)
Any ideas?
Here's a quicker solution compared to the rest:
foreach ($a as $i => $val) {
// make sure the current item is not the first one.
// because the first one is the base number
if ($i > 0) {
// Update current $i (INDEX) by
// adding the previous value ($a[$i -1]) with the current value ($val)
$a[$i] = $a[$i - 1] + $val;
}
}
As 0 is the first value, we can't increment before it :) hence the if statement
And here is a demo: Example
It doesn't matter about what looping method you use, it's how you apply it. Look, here's the exact same thing done in a for loop:
for($i = 0; $i < count($a); $i++) {
if($i > 0) {
$a[$i] = $a[$i - 1] + $a[$i];
}
}
It all comes down to the preference of the coder using it.
Both of those loops return the correct data:
Array
(
[0] => 460
[1] => 485
[2] => 510
[3] => 535
[4] => 560
[5] => 585
[6] => 610
)
Like this?
$source = array(460, 25, 25, 25, 25, 25, 25);
$result = array();
$last = 0;
foreach($source as $s){
$last = $result[] = $s+$last;
}
$previous = 0;
foreach ($a as $key => &$value)
$previous = $value = $previous + $value;
or
$sum = 0;
foreach ($a as $key => &$value)
{
$sum += $value;
$value = $sum;
}
Get the value of the previous index (do check if index > 0), and add it to the current value.
$values = array(
460,
25,
25,
25,
25,
25,
25
);
foreach($values as $key => &$value){
if($key > 0){
$prev_value = $values[$key-1];
$value += $prev_value;
}
}
echo print_r($values);
$array1 = (460, 25, 25, 25, 25, 25, 25);
function calculateAdjecentSum($array1)
{
$array2 = array();
$pointer = 0;
foreach ($array1 as $number) {
$sum = $pointer + $number;
$array2[] = $sum;
$pointer = $sum;
}
return $array2;
}
It's enough to use for loop:
<?php
$array = array
(
0 => 460,
1 => 25,
2 => 25,
3 => 25,
4 => 25,
5 => 25,
6 => 25,
);
for ($i=1, $c = count($array); $i<$c; ++$i) {
$array[$i] += $array[$i-1];
}
var_dump($array);
I have no idea why all other answers use foreach loop in this case as for in my opinion is better to do that (no conditions, no temporary variables, no unset references from foreach).
You can do like this
<?php
$yourarray = array(460, 25, 25, 25, 25, 25, 25);
$l = 0;
foreach($yourarray as $b){
$l = $b+$l;
echo $last;
}
Outputs 460485510535560585610
Try this :
<?php
$array = array( 460, 25, 25, 25, 25, 25, 25);
$result = array();
for ($i=count($array);$i>0; $i--){
$result[($i-1)] = array_sum($array);
array_pop($array);
}
echo "<pre>";
ksort($result);
print_r($result);
?>
Output :
Array
(
[0] => 460
[1] => 485
[2] => 510
[3] => 535
[4] => 560
[5] => 585
[6] => 610
)

Sum certain indice values in MultiDimensional Array

I have the following:
Array
(
[0] => Array
(
[department] => Central>ACME>BusDev
[Total_Staff] => 4
[Total_Resp] => 0
)
)
There are over 150 of these within the array.
I can easily sum, for example, Total_Staff and Total_Resp using something like:
foreach($arr as $num => $values) {
$sum_staff += $values[ 'Total_Staff' ];
$sum_resp += $values[ 'Total_Resp' ];
}
However what I need to do is sum only elements of the array, for example I need to sum Total_Staff and Total_resp that lies between indexes 0 and 7 or 12 and 58.
Not sure how to go about this.
Is this what you need
foreach($arr as $num => $values) {
if(($num >= 0 && $num <= 7) || ($num >= 12 && $num <= 58))
$sum += $values[ 'Total_Staff' ];
}
Using a for loop would be the way to solve this:
$start = 12;
$end = 58;
$sum_total_staff = 0;
$sum_total_resp = 0;
for( $i = $start; $i <= $end; $i++ ) {
$sum_total_staff += $arr[$i]["Total_Staff"];
$sum_total_resp += $arr[$i]["Total_Resp"];
}
Id say use these 2 function to slice & merge the arrays. It will get 8 arrays from which are between indexes 0-7 (with 0 and 7 included) and same with the second one. If you want without 0 and 7, it would be with arguments 1, 6, so array_slide($arr, 1, 6); and so on.
$new_arr1 = array_slice($arr, 0, 8);
$new_arr2 = array_slice($arr, 12, 47);
$arr = array_merge($new_arr1, $new_arr2);

Intersection of arrays in PHP. Finding matching Pairs

I've got an array like this:
$a = array(
array(2 => 1, 4 => 2, 9 => 3),
array(3 => 7, 4 => 5, 7 => 3),
array(1 => 6, 4 => 5),
...
);
So the array contains a huge amount of sub arrays with integer key => integer value.
Now I want to find subarrays which share no keys or if they share a key the value of this key must be the same.
Example: $a[1] and $a[2] would match because $a[1][4] == $a[2][4] and no other keys match. But $a[0] and $a[1] would not match because $a[0][4] != $a[1][4].
The number of elements in the subarrays may vary.
Is there an efficient way to do this ? The only way I can think of is check each possible pair in a nested loop resulting in O(n^2).
If someone has an idea for a more meaningful title feel free to edit it.
Maybe code makes it more clear: (naive implementation)
$pairs = array();
for($i = 0; $i < count($a); $i++)
for($j = $i+1; $j < count($a); $j++)
if(array_intersect_key($a[$i], $a[$j]) == array_intersect_assoc($a[$i], $a[$j]))
$pairs[] = array($i, $j);
Alternative:
$matching = array();
for($i = 0; $i < count($a); $i++)
for($j = $i+1; $j < count($a); $j++)
if(array_intersect_key($a[$i], $a[$j]) == array_intersect_assoc($a[$i], $a[$j]))
list($matching[$i][], $matching[$j][]) = array($j, $i);
There might be ways to do it, but it somewhat depends on if you know how many matches are likely (or the general 'matchyness' of your data). If there's more matches than not it might be better to start with assuming everything matches and eliminating.
In any case, I think you can pre-process the data. I'm not sure if this is faster -- it really depends on the distribution of your data, but I'd start by trying something like this and work from there:
$a = array(
array(2 => 1, 4 => 2, 9 => 3),
array(3 => 7, 4 => 5, 7 => 3),
array(1 => 6, 4 => 5),
array(1 => 6, 4 => 5, 7 => 5),
array(2 => 1, 4 => 2, 9 => 3)
);
// 1 and 2 match, 2 and 3 match, 0 and 4 match
$keyData = array();
for ($i = 0; $i < count($a); $i++) {
foreach($a[$i] as $k => $v) {
if (!isset($keyData[$k])) {
$keyData[$k] = array();
}
if (!isset($keyData[$k][$v])) {
$keyData[$k][$v] = array();
}
$keyData[$k][$v][] = $i;
}
}
$potentialMatches = array();
foreach ($keyData as $key => $values) {
// Ignore single key/value pairs
if (count($values) > 1) {
foreach ($values as $value => $arrayIndices) {
for ($i = 0; $i < count($arrayIndices); $i ++) {
for ($j = $i + 1; $j < count($arrayIndices); $j ++) {
$potentialMatches[] = array($arrayIndices[$i], $arrayIndices[$j]);
}
}
}
}
}
// You might need to do this ...
/*
foreach ($potentialMatches as &$m) {
array_unique($m);
}
*/
$pairs = array();
foreach ($potentialMatches as $m) {
if(array_intersect_key($a[$m[0]], $a[$m[1]])
== array_intersect_assoc($a[$m[0]], $a[$m[1]])) {
$pairs[] = $m;
}
}
print_r($pairs);
Output:
Array
(
[0] => Array
(
[0] => 0
[1] => 4
)
[1] => Array
(
[0] => 1
[1] => 2
)
[2] => Array
(
[0] => 2
[1] => 3
)
)
EDIT
As I said in my comment, that doesn't catch arrays that don't share any keys -- which you consider a match. The code below does this, although I'm not sure if it's faster than the nested solution (and it's going to use a ton of memory)
// New test data to cover the case I missed
$a = array(
array(2 => 1, 4 => 2, 9 => 3),
array(3 => 7, 4 => 5, 7 => 3),
array(1 => 6, 4 => 5),
array(1 => 6, 4 => 5, 7 => 5),
array(2 => 1, 4 => 2, 9 => 3),
array(8 => 3)
);
// 1 and 2 match, 2 and 3 match, 0 and 4 match, 5 matches all
// First assume everything is a match, build an array of:
// indicies => array of potential matches
$potentialMatches = array_fill(0, count($a), array_keys($a));
// Build data about each key, the indicies that contain that key
// and the indicies for each value of that key
$keyData = array();
for ($i = 0; $i < count($a); $i++) {
foreach($a[$i] as $k => $v) {
if (!isset($keyData[$k])) {
$keyData[$k] = array();
}
if (!isset($keyData[$k][$v])) {
$keyData[$k][$v] = array();
}
$keyData[$k]['all'][] = $i;
$keyData[$k][$v][] = $i;
}
}
// print_r($keyData);
// Now go through the key data and eliminate indicies that
// can't match
foreach ($keyData as $key => $values) {
if (count($values) > 2) { // Ignore single key/value pairs
// Two indecies do not match if they appear in seperate value lists
// First get the list of all indicies that have this key
$all = array_unique($values['all']);
unset($values['all']);
// Now go through the value lists
foreach ($values as $value => $arrayIndices) {
// The indicies for this value cannot match the other
// indices in the system, i.e. this list
$cantMatch = array_diff($all, $arrayIndices);
// So remove the indicies that can't match from the potentials list
foreach ($arrayIndices as $index) {
$potentialMatches[$index] = array_diff($potentialMatches[$index], $cantMatch);
}
}
}
}
//print_r($potentialMatches);
// You said you didn't mind the output format, so that's probably enough
// but that array contains (x,x) which is pointless and both (x,y) and (y,x)
// so we can do one final bit of processing to print it out in a nicer way
$pairs = array();
foreach ($potentialMatches as $x => $matches) {
foreach ($matches as $y) {
if ( ($x < $y) ) {
$pairs[] = array($x, $y);
}
}
}
print_r($pairs);
Output
Array
(
[0] => Array
(
[0] => 0
[1] => 4
)
[1] => Array
(
[0] => 0
[1] => 5
)
[2] => Array
(
[0] => 1
[1] => 2
)
[3] => Array
(
[0] => 1
[1] => 5
)
[4] => Array
(
[0] => 2
[1] => 3
)
[5] => Array
(
[0] => 2
[1] => 5
)
[6] => Array
(
[0] => 3
[1] => 5
)
[7] => Array
(
[0] => 4
[1] => 5
)
)
if you are looking for adjacent matching,
$temp = null;
$last_result = array();
foreach($a as $key => $value){
if(is_null($temp)){
$temp = $value;
} else{
$result = array_intersect_assoc($temp, $value);
if(!empty($result))
array_push($last_result, $result);
$temp = $value;
}
}
print_r($last_result);
otherwise just use array_intersect_assoc
for a example you can do like this
$res = array_intersect_assoc($a[0],$a[1],$a[2]);
print_r($res);

Categories