It is hard to explain, but i will try my best.
In html, got a row of item A B C D E. They are not in array.
Now got another array which is Num[]={1,2,3,4,5,6,7,8,9}.
Imagine A=1, B=2, C=3, D=4, E=5, 0=6, 0=7, 0=8, 0=9.
Now, i use checkbox to check the item B,C,E and form an array check[]={B,C,E}.
Question is: How to know that the new array check[0]=2, check[1]=3, check[2]=5?
Sorry, i cant explain well, for me its complicated.(no code provided because its too long)
Using array_intersect() which matches the two arrays up (the first one and the one with the values you want to find) gives you an array with just those items and the keys from the first array. You can then use array_intersect_key() which extracts the items from the second array with the keys extracted in the first step.
$a1 = ['A', 'B', 'C', 'D', 'E'];
$a2 = [1,2,3,4,5];
$a3 = ['A', 'D'];
$a4 = array_intersect_key($a2, array_intersect($a1, $a3));
print_r($a4);
which outputs...
Array
(
[0] => 1
[3] => 4
)
You can use array_values() if you want the keys to be sequential.
$a4 = array_values(array_intersect_key($a2, array_intersect($a1, $a3)));
Try with array_map
$abc = array('A', 'B', 'C', 'D', 'E');
$num = array(1, 2, 3, 4, 5);
$newAbc = array('A', 'D');
$newNum = array_map(function($element) use($abc, $num) {
return $num[array_search($element, $abc)];
}, $newAbc);
// Outputs: 1, 4
print_r($newNum);
The array_intersect solution is very clean too :)
A simple solution would be a map, which maps the content ABC to Num.
$abc = ['A', 'B', 'C', 'D', 'E'];
$num = [1, 2, 3, 4, 5];
$map = [];
foreach ($abc as $index => $val) {
$map[$val] = $num[$index];
}
$x = ['A', 'D'];
foreach ($x as $index => $val) {
echo "x[$index] = {$map[$val]}\n";
}
If you have to do this only for one element, you could also skip the map creation part and use array_search;
echo $num[array_search('A', $abc)];
<?php
$chars = ['A', 'B' , 'C' , 'D' , 'E'];
$ints = [ 1 , 2 , 3 , 4 , 5];
$given = ['A', 'D'];
$require = [1, 4];
Combine and intersect:
$ints_chars = array_combine($ints, $chars);
var_export($ints_chars);
$result = array_keys(array_intersect($ints_chars, $given));
var_dump($result === $require);
Output:
array (
1 => 'A',
2 => 'B',
3 => 'C',
4 => 'D',
5 => 'E',
)bool(true)
Use a map:
$result = [];
$chars_ints = array_combine($chars, $ints);
foreach($given as $char)
$result[] = $chars_ints[$char];
var_dump($result === $require);
Output:
bool(true)
Use a map, but notice your number range is just a shifted index:
$result = [];
$chars_flip = array_flip($chars);
foreach($given as $char)
$result[] = $chars_flip[$char] + 1;
var_dump($result === $require);
Output:
bool(true)
Finally by shifting and mutating the original array:
array_unshift($chars, null);
$result = array_keys(array_intersect($chars, $given));
var_dump($result === $require);
Output:
bool(true)
Related
I'm trying to create a script to create pairs from 2 different arrays. For example I have two array given below:
<?php
//Array 1
$arr1 = array('A', 'B', 'C', 'D');
//Array 2
$arr2 = array('X', 'Y', 'Z');
And I need output in such a manner so that it match with each element and didn't repeat pair and sequence also. Here is expected output:
$output = array(
0 => array('A', 'X'),
1 => array('B', 'Y'),
2 => array('C', 'Z'),
3 => array('D', 'X'),
4 => array('A', 'Y'),
5 => array('B', 'Z'),
6 => array('C', 'X'),
7 => array('D', 'Y'),
8 => array('A', 'Z'),
9 => array('B', 'X'),
10 => array('C', 'Y'),
11 => array('D', 'Z')
)
**Note: 2 arrays can differ with number of count and values.
This is Cartesian Product. Could be achieved with
//Array 1
$arr1 = array('A', 'B', 'C', 'D');
//Array 2
$arr2 = array('X', 'Y', 'Z');
$output = array();
foreach($arr1 as $i1){
foreach ($arr2 as $i2) {
$output[] = array($i1, $i2);
}
}
echo json_encode($output);
If you want the output to be in the same order as you have mentioned above, following should do that.
$newoutput = array();
$x = 0;
$y = 0;
for($i = 1; $i <= (count($arr1) * count($arr2)); $i++){
$newoutput[] = array($arr1[($x % count($arr1))], $arr2[($y % count($arr2))]);
$x++;
$y++;
}
echo "<br />", json_encode($newoutput);
Output however, is a different order of the same output as previous.
EDIT
The second works only when (count($arrX) % count($arrY)) > 0.
I don't think there is a built in support for that.
You need to loop the arrays nested and build a result array.
$arr1 = array('A', 'B', 'C', 'D');
$arr2 = array('X', 'Y', 'Z');
foreach($arr1 as $item1){
foreach($arr2 as $item2){
$res[] = [$item1, $item2];
}
}
var_dump($res);
https://3v4l.org/CdE8Q
Try This out (This will sort out the same pair if found):
//Array 1
$arr1 = array('A', 'B', 'C', 'D', 'A', 'E'); // Same element will be sort out in pair
//Array 2
$arr2 = array('X', 'Y', 'Z' , 'X', 'Y', 'X'); // Same element will be sort out in pair
$output = array();
$used_pair = array(); // Keeping used pair
$i = 1;
foreach ($arr1 as $each1) {
foreach ($arr2 as $each2) {
if (!in_array($each1.$each2, $used_pair)) {
$output[] = array($each1, $each2);
$used_pair[] = $each1 . $each2;
}
}
}
print_r($used_pair); // array with pair string
print_r($output); // array with pair array
this is an example that ouputs unique values in the same order :
online eval : https://3v4l.org/H2pad
<?php
function cartesian(array $x,array $y): array
{
$result = [];
$size = count($x) * count($y);
$posX = 0;
$posY = 0;
for($i = 0; $i < $size; $i++) {
if (!isset($x[$posX])) {
$posX = 0;
} elseif(!isset($y[$posY])) {
$posY = 0;
}
$result[] = [$x[$posX],$y[$posY]];
$posX++; $posY++;
}
return $result;
}
$x = array('A', 'B', 'C', 'D');
$y = array('X', 'Y', 'Z');
print_r(cartesian($x,$y));
( tbh, it took me a lot of rubber duck debugging )
I have two random arrays merged, everything displaying/functioning beautifully. The one stuck I have is this:
When I merge the two arrays together I need to make sure that every 3 item comes from array2.
array1 (a,b,c,d,e,f,g,h,i,j,k)
array2 (a1,a2,a3,a4)
My desired outcome:
d k c a1 j i g a2 etc.
What I have done so far:
function randomize_blocks($arr, $num = 1) {
shuffle($arr);
$r = array();
for ($i = 0; $i < $num; $i++) {
$r[] = $arr[$i];
}
return $num == 1 ? $r[0] : $r;
}
//gather donor blocks into an array
$donorBlocks = array($blockA, $blockB, $blockC, $blockD, $blockE, $blockF,
$blockG, $blockH, $blockI, $blockJ, $blockK, $blockL, $blockM, $blockN,
$blockO);
//gather value blocks into an array
$valueBlocks = array($valueA, $valueB, $valueC, $valueD);
//shake that shuffler real hard! DT
$shuffled_valueBlocks = randomize_blocks($valueBlocks, 4);
$shuffled_donorBlocks = randomize_blocks($donorBlocks, 15);
//combine our shuffled arrays together
$combinedArrays = array_merge($shuffled_valueBlocks, $shuffled_donorBlocks);
//shuffle them all together!
$shuffled_blocks = randomize_blocks($combinedArrays, 19);
//display bocks on page
foreach ($combinedArrays as $key => $value) {
echo $value;
}
What is the best way to accomplish this?
Here is a way with array_splice to modify the longest of the two arrays into the desired result:
$a = ['a', 'b', 'c', 'd'];
$b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
foreach ($a as $i => $v)
array_splice($b, $i*4+3, 0, [$v]);
$b will be:
[1, 2, 3, 'a', 4, 5, 6, 'b', 7, 8, 9, 'c', 10, 11, 12, 'd', 13, 14, 15]
What about something like this?
$a1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'];
$a2 = ['a1', 'a2', 'a3', 'a4'];
$a = [];
shuffle($a1);
foreach ($a1 as $k => $v) {
$a[] = $v;
if (($k + 1) % 3 === 0 && $a2) $a[] = array_shift($a2);
}
This is based on the assumption that you want both arrays shuffled as well as placed in your desired pattern:
$array_one = array('a','b','c','d','e','f','g','h','i','j','k');
$array_two = array('a1','a2','a3','a4');
function merge_random_interval($array_one = array(), $array_two = array(), $interval = 3) {
$return_array = array();
// Shuffle the arrays - that seems to be important?
shuffle($array_one);
shuffle($array_two);
// Go through the first array
$array_two_index = 0;
for ($i = 0; $i < count($array_one); $i++) {
// Every $interval add a value from the second array
if ($i > 0 && $i % $interval == 0) {
// Make sure there is a value in the second array
if (isset($array_two[$array_two_index])) {
$return_array[] = $array_two[$array_two_index];
$array_two_index++;
}
}
$return_array[] = $array_one[$i];
}
// You may want to check if $array_two has more values that weren't added?
// Compare $array_two_index against count($array_two)
return $return_array;
}
$result_array = merge_random_interval($array_one, $array_two, 3);
echo implode(' ', $result_array); // g d c a1 h i j a4 b e a a2 k f
i have two arrays in php and i am using the array_intersect function to find the common elements and if common elements exists i want to display the index of theses common elements in the 1st array
here is what i have done so far..
function check_if_exists($company_timings,$in_time)
{
$length_of_company=sizeof($company_timings);
$length_of_emp=sizeof($in_time);
$common=array_intersect($company_timings,$in_time);
$length_of_common=sizeof($common);
$key=array_search($common,$company_timings);
return $key;
}
but its not return the keys there are common elements which are 09:00:00 and 11:00:00 and when i pass 11:00:00 rather than $common in array_search then it gives the accurate result other wise with the $common_array it doesn't work,,,kindly help me in ameliorating the code
This function returns an array containing the common elements and their positions in both array, or falseif no common elements are found :
function check_if_exists($arr1, $arr2) {
$combined = array_intersect($arr1, $arr2);
if (empty($combined))
return false;
$return = array();
foreach ($combined as $elmt) {
$return[$elmt] = array();
$return[$elmt]['arr1'] = array_search($elmt, $arr1);
$return[$elmt]['arr2'] = array_search($elmt, $arr2);
}
return $return;
}
Test :
$array1 = array('a', 'b', 'c', 'd');
$array2 = array('b', 'f', 'g', 'c');
$array3 = array('n', 'o', 'p', 'e');
$exists = check_if_exists($array1, $array2);
var_dump($exists);
$exists_no = check_if_exists($array1, $array3);
var_dump($exists_no);
Output :
array (size=2)
'b' =>
array (size=2)
'arr1' => int 1
'arr2' => int 0
'c' =>
array (size=2)
'arr1' => int 2
'arr2' => int 3
boolean false
Try with array_keys function
Here is an example code. Hope it will help you.
<?php
$a = array("a","b","c");
$b = array("c","d","a");
$c = array_keys(array_intersect($a,$b));
var_dump($c);
?>
An array of values are provided in the order they should appear in columns. For example, the second value in the array should be displayed on a webpage beneath the first instead of on its right.
Task: Reorder the array so that the values are in the order they will be output in html. The data for the first row must be first in the output.
Example inputs:
$input = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
$cols = 2;
Example output:
[['A', 'E'], ['B','F'], ...]
Use array_chunk() to break the array up in to $cols:
$chunks = array_chunk($array, ceil(count($array) / $cols));
Which would give you:
array(array('A', 'B', 'C', 'D'), array('E', 'F', 'G'));
Then combine the values from each array where the keys match.
array_unshift($chunks, null);
$chunks = call_user_func_array('array_map', $chunks);
// array(array('A', 'E'), array('B', 'F'), array('C', 'G'), array('D', NULL))
Here's an example
You need to count offset and then iterate over an array:
$input = array('A', 'B', 'C', 'D', 'E', 'F', 'G');
$cols = 2;
$itemsCount = count($input);
$offset = ceil($itemsCount/$cols);
$result = array();
for($i = 0; $i < $itemsCount; ++$i) {
if (isset($input[$i]) && isset($input[$i + $offset])) {
$result[] = array($input[$i], $input[$i + $offset]);
}
}
The modern functional equivalent of #billyonecan's approach uses the spread operator to transpose the data after it has been "chunked" to the correct size. (Demo)
$input = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
$cols = 2;
var_export(
array_map(
null,
...array_chunk($input, ceil(count($input) / 2))
)
);
// [['A', 'E'], ['B', 'F'], ['C', 'G'], ['D', null]]
A classic loop alternative using a modulus calculation is also attractive because it doesn't generate the extra null element in the final set when the division doesn't come out even: (Demo)
$input = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
$cols = 2;
$rows = ceil(count($input) / $cols);
$result = [];
foreach ($input as $i => $value) {
$result[$i % $rows][] = $value;
}
var_export($result);
// [['A', 'E'], ['B', 'F'], ['C', 'G'], ['D']]
On this related topic, to more simply chunk and transpose with a finite number of rows, use the following: (Demo)
$rows = 2;
var_export(
array_map(
null,
...array_chunk($input, $rows)
)
);
This question already has answers here:
Merge two flat indexed arrays of equal size so that values are pushed into the result in an alternating fashion
(2 answers)
Closed 6 months ago.
I have two arrays:
A = [1, 2, 3, 4]
B = ['a', 'b', 'c', 'd']
I want to merge them into tuples (A, B) in an one-dimensional array:
C = [1, 'a', 2, 'b', 3, 'c', 4, 'd']
Is there some native function in PHP that lets you interpolate two arrays this way? If not, would a loop be the most effective and eficient way to do this?
The number of elements of A will always be the same of B.
Note: If it helps, in the context of my specific needs, array A can be summarized as a single value (since the value will be the same for all values in B).
A = 1
B = ['a', 'b', 'c', 'd']
C = [1, 'a', 1, 'b', 1, 'c', 1, 'd']
Loops are OK in this case, since PHP does not have a native function to interleave 2 arrays, but this is a nice way to solve the problem:
function interleave($array1, $array2) {
$result = array();
array_map(function ($e1, $e2) use (&$result) {
array_push($result, $e1, $e2);
}, $array1, $array2);
return $result;
}
I don't know if there is any built-in mapping function that makes this easier, but this is a simple, naive implementation.
$a = array(1,2,3,4);
$b = array('a','b','c','d');
function array_interpolate($a, $b) {
if (sizeof($a) != sizeof($b))
throw new Exception('Arrays must be of same size');
$result = array();
for ($i = 0, $l = sizeof($a); $i < $l; $i++) {
$result[2*$i] = $a[$i];
$result[2*$i+1] = $b[$i];
}
return $result;
}
$res = array_interpolate($a, $b);
print_r($res);
The above returns
Array
(
[0] => 1
[1] => a
[2] => 2
[3] => b
[4] => 3
[5] => c
[6] => 4
[7] => d
)
$C = call_user_func_array('array_merge', call_user_func_array('array_map', array(NULL, $A, $B)));
Since in PHP arrays are implemented as hash tables (Hash table on wikipedia), you won't be able to achieve your goal faster then looping through array.
Here is a simplest example:
function interpolate(array $a,array $b) {
$result = array();
for($i = 0; $i < count($a); $i++) {
$result[] = $a[$i];
$result[] = $b[$i];
}
return $result;
}