This question already has answers here:
Transpose 2d array, join second level with commas, and join first level with pipes
(5 answers)
Closed 7 months ago.
I have an array with arrays in it representing values in a database.
There are over 100 columns in the db table so the actual count is much higher than this example below of 6 values, the sub-array (Array within the array) index 0-5.
The columns are in each index of the sub-array and the rows are in each index of the main array.
Here is my main array with sub-arrays:
Array
(
[0] => Array
(
[0] => N
[1] => N
[2] => Y
[3] => Y
[4] => Y
[5] => Y
)
[1] => Array
(
[0] => N
[1] => N
[2] => Y
[3] => Y
[4] => N
[5] => Y
)
[2] => Array
(
[0] => N
[1] => N
[2] => Y
[3] => Y
[4] => N
[5] => Y
)
[3] => Array
(
[0] => Y
[1] => Y
[2] => Y
[3] => Y
[4] => Y
[5] => Y
)
What I need to do is concat all the values of each sub index into one array like this:
Array
(
[0] => N,N,N,Y
[1] => N,N,N,Y
[2] => Y,Y,Y,Y
[3] => Y,Y,Y,Y
[4] => Y,N,N,Y
[5] => Y,Y,Y,Y
)
There will always be the same number of columns (sub index) but there will be different amounts of rows (index).
The idea is get the data by column, you're in luck, there's a built in function for that. Its array_column.
So first, get the number of columns and simply use a for loop for that. Then just use implode and assign it inside a new container:
$new = array(); // container
$count = count($arr[0]); // get the number of colums
for ($i = 0; $i < $count; $i++) {
// get the data by column number ($i), then implode and push inside
$new[] = implode(',', array_column($arr, $i));
}
Here's a sample output
Avoid using explicit loops like for and while. Use array_map (it can take the variable mumber of arrays to traverse):
$result = array_map(function (...$column) {
return implode(',', $column);
}, ...$array);
Here is the demo.
By the way, in linear algebra this is called transpose of the matrix.
From PHP7.4 and higher, the same technique can be written as: (Demo)
var_export(
array_map(
fn() => implode(',', func_get_args()),
...$array
)
);
Or: (Demo)
var_export(
array_map(
fn(...$column) => implode(',', $column),
...$array
)
);
I assume that you have defined $column as the total number of column in your db table. Use array_column to get the value according to the column key.
$result = array();
for ($i = 0; $i < $column; $i++) {
$res = array_column($arr, $i);
$result[] = implode(",", $res);
}
For more information about array_column function, check this link.
Oh, just to let you know that array_column function only works for PHP 5.5 and higher.
check if this is what you want
$arr = array(//your array);
$newArr = array(); //data wil lbe saved here
foreach($arr as $arr_one){
$string = "";
foreach($arr_one as $subArr){
$string.=$subArr.",";
}
array_push($newArr,rtrim($string,','));
}
var_dump($newArr);
Related
What would be the most efficient PHP way to get unique values from an array of arrays and sort them by number of occurrences from most frequent to least?
Example input array:
Array
(
[0] => Array
(
[0] => A
[1] => B
[2] => C
[3] => D
)
[1] => Array
(
[0] => A
[1] => C
[2] => D
)
[2] => Array
(
[0] => C
[1] => F
[2] => X
)
)
Would result in this output array:
Array
(
[0] => C // 3
[1] => A // 2
[2] => D // 2
[3] => B // 1
[4] => F // 1
[5] => X // 1
)
The alphabetical order of values with same number of occurrences is not important.
So far I'm merging the array of arrays:
$all_posts = call_user_func_array( 'array_merge', $results );
Then creating a new array where values become keys. And values are the number of times they occur in the original array of arrays.
$posts_by_count = array();
foreach( $all_posts as $apost ) {
$posts_by_count[ $apost ] = 0;
foreach( $results as $tag_posts ) {
if( in_array( $apost, $tag_posts ) ) {
$posts_by_count[ $apost ]++;
}
}
}
Then I can sort by value
arsort($posts_by_count);
And create a new array where keys become values again.
$sorted_posts = array();
foreach($posts_by_count as $k => $v) {
$sorted_posts[] = $k;
}
pprint( $sorted_posts );
What would be a more efficient way to do that?
The simplest I can come up with is to start with the array_merge(), but using the splat (...) to merge all of the arrays. Then use the inbuilt array_count_values() to summarize the values and then arsort() to sort them...
$all_posts = array_merge(...$results );
$posts_by_count = array_count_values($all_posts);
arsort($posts_by_count);
This gives the output of...
Array
(
[C] => 3
[A] => 2
[D] => 2
[B] => 1
[F] => 1
[X] => 1
)
using
print_r(array_keys($posts_by_count));
gives...
Array
(
[0] => C
[1] => A
[2] => D
[3] => B
[4] => F
[5] => X
)
That's simple, first iterate to count occurences, finally use arsort() to sort it by value in descending order:
<?php
// sample data
$arr = [
['A', 'B', 'C', 'D'],
['A', 'C', 'D'],
['C', 'F', 'X']
];
// counting
$newArr = [];
foreach ($arr as $subarr) {
foreach ($subarr as $char) {
$newArr[$char] = (!array_key_exists($char, $newArr))
? 1
: $newArr[$char] = $newArr[$char] + 1;
}
}
// sort by value in DESC order
arsort($newArr);
// To get exactly what you want (without counting) just iterate $newArr and writ is as a $flatArr
$flatArr = [];
foreach ($newArr as $index => $item) {
$flatArr[] = $index;
}
// or with array_keys which _may_ be unstable #see: https://stackoverflow.com/q/10336363/1066240
$flatArrArrayKeys = array_keys($newArr);
// output
$newArrHr = print_r($newArr, 1);
$flatArrHr = print_r($flatArr, 1);
echo "<pre>OUTPUT:
With count:
$newArrHr
As flat array:
$flatArrHr
As flat array with array_keys()
$flatArrArrayKeys
";
I have this array. I want to duplicate all records form an array. I tried array_unique but it's removing duplicate but doesn't remove orignal value.
Array (
[0] => 1
[1] => 2
[2] => 3
[3] => 1
[4] => 6
[5] => 1
[6] => 23
[7] => 2
)
I want to remove all duplicate value like 1 and 2 and I want this output :
Array
(
[0] => 3
[1] => 6
[2] => 23
)
You could use a combination of array_filter and array_count_values.
$values = [1,2,3,1,6,1,23,2];
$result = array_filter(array_count_values($values), function($x) {
return $x === 1;
});
print_r(array_keys($result));
Result:
Array
(
[0] => 3
[1] => 6
[2] => 23
)
You can also use array_intersect with array_count_values.
Array_intersect returns values that is 1, and array_keys returns the keys (values).
$values = [1,2,3,1,6,1,23,2];
$result = array_keys(array_intersect(array_count_values($values), [1]));
var_dump($result); //[3,6,23]
https://3v4l.org/cHU5E
Another option is to use array_unique and the use array_diff_assoc() to get a list of what has been removed.
Using that array list in array_diff results in the values that is not duplicated.
$values = [1,2,3,1,6,1,23,2];
$diff = array_diff_assoc($values, array_unique($values));
$result = array_diff($values, $diff);
var_dump($result); //[3,6,23]
https://3v4l.org/XM5sk
How do I find the keys array of disciplines that have appropriate values?
For Example:
$arr1 = [2, 4, 12];
$result = [...] // Var_dump in link
in_array($arr1, $result);
Regardless of their order, I need to see if there is a set of keys or a no.
But in_array() does not work.
Thanks!
Dump array
Update (01.03.2017)
This is my version of the solution to this problem
$findResult = array_filter($result, function($val)use($get){
$requiredDisciplines = [1, $get['disciplines']['second'], $get['disciplines']['third'], $get['disciplines']['four']]; // запрос
$activePriorities = [];
foreach ($val['disciplines'] as $discipline) {
if (in_array($discipline['id'], $requiredDisciplines)) {
$activePriorities[] = $discipline['priority'];
}
}
for ($i = 0; $i<3; $i++){
if(!in_array($i, $activePriorities))
return false;
}
/*if(in_array(0, $activePriorities) && in_array(1, $activePriorities) && in_array(2, $activePriorities) != true)
return false;*/
// print_r($activePriorities);
return true;
});
I've got a versatile one-liner that will give you all of the arrays containing matches. (so you can derive the keys or the count from that). (demo)
This function is only set to compare the values between the needle and the haystack, but can be set to search keys-values pairs by replacing array_intersect with array_intersect_assoc and adding ,ARRAY_FILTER_USE_BOTH to the end of the filter function (reference: 2nd snippet # https://stackoverflow.com/a/42477435/2943403)
<?php
// haystack array
$result[]=array(1,2,3,4,5,6,7,8,9,10,11,12);
$result[]=array(1,3,5,7,9,11);
$result[]=array(2,4,6,8,10,12);
// needle array
$arr1=array(2,4,12);
//one-liner:
$qualifying_array=array_filter($result,function($val)use($arr1){if(count(array_intersect($val,$arr1))==count($arr1)){return $val;}});
/*
// multi-liner of same function:
$qualifying_array=array_filter(
$result,
function($val)use($arr1){ // pass in array to search
if(count(array_intersect($val,$arr1))==count($arr1)){ // total pairs found = total pairs sought
return $val;
}
}
);*/
echo 'Total sub-arrays which contain the search array($arr1): ',sizeof($qualifying_array),"<br>";
echo 'Keys of sub-arrays which contain the search array($arr1): ',implode(',',array_keys($qualifying_array)),"<br>";
echo 'Is search array($arr1) in the $result array?: ',(sizeof($qualifying_array)?"True":"False"),"<br>";
echo "<pre>";
print_r($qualifying_array);
echo "</pre>";
The output:
Total sub-arrays which contain the search array($arr1): 2
Keys of sub-arrays which contain the search array($arr1): 0,2
Is search array($arr1) in the $result array?: True
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
[8] => 9
[9] => 10
[10] => 11
[11] => 12
)
[2] => Array
(
[0] => 2
[1] => 4
[2] => 6
[3] => 8
[4] => 10
[5] => 12
)
)
There is an array containing K elements. What's the best way to get chunks of N < K items from this array?
Example input:
$x = [1,2,3,4,5,6,7,8,9,10]; // K = 10
Desired result, when N = 3;
$x1 = [1,2,3];
$x2 = [4,5,6];
$x3 = [7,8,9];
$x4 = [10];
Obviously, there is no need to store the result in variables. As long as it's possible to process it by foreach (or any other iteration logic), it should be fine.
The problem with array_slice is that it does not remove the N-slice from the beginning of the array. The problem with array_shift is that it does not support shifting more than 1 item at once. Is there anything more elegant than iterating over array_shift?
array_chunk is what you need.
<?php
$x = [1,2,3,4,5,6,7,8,9,10];
print_r(array_chunk($x,3));
OUTPUT :
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[1] => Array
(
[0] => 4
[1] => 5
[2] => 6
)
[2] => Array
(
[0] => 7
[1] => 8
[2] => 9
)
[3] => Array
(
[0] => 10
)
)
Look into array_chunk -> http://www.w3schools.com/php/func_array_chunk.asp
$x = [1,2,3,4,5,6,7,8,9,10];
print_r(array_chunk($x,3,true));
or you could do it this way -
$x = [1,2,3,4,5,6,7,8,9,10];
$chunks = array();
while(count($x)){
$chunks[] = array_splice($x, 0,3,array());
$i++;
}
Could someone tell me which method would be more efficient?
array_chunk function is used to create sub arrays of equal size.
E.g.
$a=array_chunk($array,3);
I have an array data that look like this :
Array (
[0] => Array (
[0] => Name:
[1] => John W.
[2] => Registration ID:
[3] => 36
)
[1] => Array (
[0] =>Age:
[1] => 35
[2] => Height:
[3] => 5'11"
)
[3] => Array (
[0] => Sex:
[1] => M
[2] => Weight:
[3] => 200lbs
)
[4] => Array (
[0] => Address
)
[5] => Array (
[0] => 6824 crestwood dr delphi, IN 46923
))
And I want to convert it to associative array like this :
Array(
['Name']=> John W.
['Registration ID']=> 36
['Age']=> 35
['Height'] => 5'11''
['Sex']=>M
['Weight']=>200lbs
['Address']=>6824 crestwood dr delphi, IN 46923
)
I have no idea at all how to do this, since the supposed to be array column header were also in sequence, so it makes difficult to convert this array.
Any help I appreciate, thx.
Given your origin array is called $origin , you can do it like this:
$merged = array();
foreach($origin as $val) {
$merged = array_merge($merged, $val);
}
$tot = count($merged) - 1;
for ($i=0;$i<$tot;$i+=2) {
$result[$merged[$i]] = $merged[$i+1];
}
var_dump($result); // To test the resulting array
Firstly, I use array_merge() to flatten the $origin array to only one dimension/depth, so we later iterate it (stepping each 2 items per iteration) and assigning each pair of items ($i and $i+1) to the resulting array.
Looks like, for the first 3 children, you can just assign the even value to the previous element as key. Then, assign the fourth one as key for fifth element.
$result = array();
foreach ($array as $key => $value)
{
if ($key < 4) {
$elements = array_values($value);
$result[$elements[0]] = $elements[1];
$result[$elements[2]] = $elements[3];
}
if ($key == 4)
$fifthkey = $value;
if ($key == 5)
$result[$fifthkey] = $value;
}
Also, note that you have to escape your height string quotes.