I've got the following array, containing ordered but non consecutive numerical keys:
Array
(
[4] => 2
[5] => 3
[6] => 1
[7] => 2
[8] => 1
[9] => 1
[10] => 1
)
I need to split the array into 2 arrays, the first array containing the keys below 5, and the other array consisting of the keys 5 and above. Please note that the keys may vary (e.g. 1,3,5,10), therefore I cannot use array_slice since I don't know the offset.
Do you know any simple function to accomplish this, without the need of using a foreach ?
Just found out array_slice has a preserve_keys parameter.
$a = [
4 => 2,
5 => 3,
6 => 1,
7 => 2,
8 => 1,
9 => 1,
10 => 1
];
$desired_slice_key = 5;
$slice_position = array_search($desired_slice_key, array_keys($a));
$a1 = array_slice($a, 0, $slice_position, true);
$a2 = array_slice($a, $slice_position, count($a), true);
you could use array_walk, passing in the arrays you wish to add the keys to by reference using the use keyword - something along the lines of this should work:
$splitArray = [1 => 2, 3 => 1, 5 => 2, 7 => 1, 9 => 3, 10 => 1];
$lt5 = [];
$gt5 = [];
array_walk($splitArray, function(&$val, $key) use (&$lt5, &$gt5) {
$key < 5 ? $lt5[] = $key : $gt5[] = $key;
});
var_dump($lt5, $gt5);
Related
This question already has answers here:
Push elements from one array into rows of another array (one element per row)
(4 answers)
Closed 5 months ago.
I need to evenly/synchronously push values from my second array into the rows of my first array.
The arrays which have the same size, but with different keys and depths. The first is an array of rows and the second is a flat array.
$array1 = [
12 => [130, 28, 1],
19 => [52, 2, 3],
34 => [85, 10, 5]
]
$array2 = [4, 38, 33]
Preferred result:
[
12 => [130, 28, 1, 4],
19 => [52, 2, 3, 38],
34 => [85, 10, 5, 33]
]
(I would like to keep the same indices of array 1, however it is not mandatory.)
I have tried these methods, but none of them work because the first array keys are unpredictable.
$final = [];
foreach ($array1 as $idx => $val) {
$final = [$val, $array2[$idx]];
}
Another:
foreach ($array1 as $index => $subArray) {
$array1 [$index][] = $array2[$index];
}
Here is one way to do this:
$merged = array_map('array_merge', $array1, array_chunk($array2, 1));
$result = array_combine(array_keys($array1), $merged);
The second step with array_combine is necessary to reapply the non-sequential keys because array_map won't preserve them in the first step.
An example using foreach
<?php
$a = [
2 => [130, 28, 1, 1, 6],
3 => [52, 2, 3, 3, 27]
];
$b = [5, 38];
$output = [];
$idx = 0;
foreach ($a as $key => $value) {
$value[] = $b[$idx];
$output[$key] = $value;
++$idx;
}
print_r($output);
Sandbox HERE
You can loop $array1 using a foreach to get the current key $index
Get the value from $array2 by using a counter as the array key which, is incremented by 1 for every iteration.
Then add the value to the end of the current array.
$array1 = [
2 => [130, 28, 1, 1, 6],
3 => [52, 2, 3, 3, 27],
13 => [41, 20, 27, 13, 37]
];
$array2 = [89, 99, 109];
$counter = 0;
foreach ($array1 as $index => $subArray) {
$array1[$index][] = $array2[$counter++];
}
print_r($array1);
Output
Array
(
[2] => Array
(
[0] => 130
[1] => 28
[2] => 1
[3] => 1
[4] => 6
[5] => 89
)
[3] => Array
(
[0] => 52
[1] => 2
[2] => 3
[3] => 3
[4] => 27
[5] => 99
)
[13] => Array
(
[0] => 41
[1] => 20
[2] => 27
[3] => 13
[4] => 37
[5] => 109
)
)
See a PHP demo.
Maintaining a counter while iterating is a simple way of accessing second array values while iterating the first. It is not necessary to make multiple passes of the arrays, just one iteration is all that is required.
Codes: (Demos)
a mapper:
$i = -1;
var_export(
array_map(fn($row) => array_merge($row, [$array2[++$i]]), $array1)
);
a looper:
$i = -1;
foreach ($array1 as &$row) {
array_push($row, $array2[++$i]);
}
var_export($array1);
a walker:
$i = -1;
array_walk($array1, fn(&$row, $k) => array_push($row, $array2[++$i]));
var_export($array1);
If you don't care about preserving the first array's keys in the result array, then you can simply use:
var_export(
array_map('array_merge', $array1, array_chunk($array2, 1))
);
I have an array in PHP.
For example :
Array
(
[3] => 6
[2] => 4
[1] => 2
[4] => 8
[6] => 12
)
I need to shift the position of each value to the next index.
ie, The desired output is
Array
(
[3] => 12
[2] => 6
[1] => 4
[4] => 2
[6] => 8
)
I need to keep the keys unchanged and round shift the values.
Which is the simplest method to attain it?
What I already tried is
$lastValue = $array[array_keys($array)[4]];
$firstKey = array_keys($array)[0];
for ($i=4; $i>0; $i--) {
$array[array_keys($array)[$i]] = $array[array_keys($array)[$i-1]];
}
$array[$firstKey] = $lastValue;
print_r($array);
php is so coool ^_^
part of the idea ~stolen~ taken from #Peters solution, sorry, mate :)
<?php
$array =
[
3 => 6,
2 => 4,
1 => 2,
4 => 8,
6 => 12,
];
$newArray = array_combine(array_keys($array), array_merge([array_pop($array)], $array));
var_dump($newArray);
demo
You can do a round shift on the value. Demo
$array =
[
3 => 6,
2 => 4,
1 => 2,
4 => 8,
6 => 12,
];
$values = [null];
$keys = [];
foreach($array as $k => $v){
$keys[] = $k;
$values[] = $v;
}
$values[0] = $v;
array_pop($values);
$result = array_combine($keys,$values);
print_r($result);
I have this code:
$ItemID = 'a62442e2-ca1f-4fd1-b80d-0d0dc511758e';
$GET_FreeTextFields = new \Picqer\Financials\Exact\ItemExtraField($connection);
$FreeTextFields = $GET_FreeTextFields->filter("ItemID eq guid'$ItemID'", '', '' );
$FreeTextFields01 = array();
$FreeTextFields02 = array();
foreach($FreeTextFields as $GET_FreeTextFields){
$FreeTextFields01[] = $GET_FreeTextFields->Value;
$FreeTextFields02[] = $GET_FreeTextFields->Number;
}
print_r($FreeTextFields01);
print_r($FreeTextFields02);
This outputs:
Value Array
(
[0] => 390
[1] => 804715
[2] => WW001
[3] => WHT/WHT/WHT
[4] => 39/42
[5] => 804715 WW00139/42
[6] => 3pk Quarter Socks
)
Numbers Array
(
[0] => 3
[1] => 4
[2] => 5
[3] => 6
[4] => 7
[5] => 8
[6] => 10
)
What this needs to output:
What i want if i use the first output so with 6 values in the array:
$FreeTextField01 = null
$FreeTextField02 = null
$FreeTextField03 = 390
$FreeTextField04 = 804715
$FreeTextField05 = WW001
$FreeTextField06 = WHT/WHT/WHT
$FreeTextField07 = 39/42
$FreeTextField08 = 804715 WW00139/42
$FreeTextField09 = null
$FreeTextField10 = 3pk Quarter Socks
But with other $ItemID, it can also output:
Value Array
(
[0] => 10100153
[1] => 2007
[2] => 350
[3] => 804082
[4] => WW006
[5] => WHT/NNY/OXGM
[6] => 35/38
[7] => 804082 WW00635/38
[8] => 0,00138857
[9] => Champion 3pk Quarter Socks
)
Numbers Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
[8] => 9
[9] => 10
)
What i want is that if a variable is not in the numbers list so 1-10, setting it to empty, and if the numbers is in the numbers array setting that number to the corresponding value variable. For example the number at [0] is 1 then set the variable $FreeTextField1 to $NumbersArray[0]->Value.
I keep making all kinds off loops but i just get stuck at the fact that the array length changes so that [6] can be the number 10 at one $itemID, but at another $ItemID, the number can be 6.
I tried researching this but I don't even know what I have to type in google to find this problem, that's why I'm describing it here.
edit i tried describing it a second time:
Yeah I'm having problems describing what i want, so let me try again. I get two arrays as output one with numbers that correspond with place it stands, as example you have FreeTextField0 thru FreeTextField10. What i tried to do is if (Numbers[0] == 0){ $FreeTextField0 = Value[0]}, but then I get the problem that Numbers[0] can be 3 or something else because if FreeTextField1 is empty i don't get a null value but nothing.
What i want if i use the first output so with 6 values in the array:
$FreeTextField01 = null
$FreeTextField02 = null
$FreeTextField03 = 390
$FreeTextField04 = 804715
$FreeTextField05 = WW001
$FreeTextField06 = WHT/WHT/WHT
$FreeTextField07 = 39/42
$FreeTextField08 = 804715 WW00139/42
$FreeTextField09 = null
$FreeTextField10 = 3pk Quarter Socks
I think this is what you're after but I have to say that I think you're barking up the wrong tree here. You really should not dynamically create variables in your script. To me, it is a serious code-smell and I think you should evaluate your design here.
http://sandbox.onlinephpfunctions.com/code/b245a0218ce174e68508139872f394def5409b05
<?php
// Test case
$values = [
'390',
'804715',
'WW001',
'WHT/WHT/WHT',
'39/42',
'804715 WW00139/42',
'3pk Quarter Socks'
];
$numbers = [3, 4, 5, 6, 7, 8, 10];
// Flip the $numbers array and then use the keys to find the corresponding values in the $values array
$intersection = array_unique(array_intersect_key($values, array_flip($numbers)));
// Fill in the missing keys and use `null` as the value
$output = $intersection + array_fill_keys(range(1,10), null);
// Sort the final output by the keys
ksort($output);
// Format the keys to match FreeTextField{00}
$output = array_combine(
array_map(function($k){ return 'FreeTextField'.str_pad($k, 2, '0', STR_PAD_LEFT); }, array_keys($output)),
$output
);
// Use the extract function to bring all those array keys + values into the symbol table.
// You can now use $FreeTextField01 - $FreeTextField10
extract($output);
var_dump($output);
UPDATE
http://sandbox.onlinephpfunctions.com/code/244c4f1ed45db398c48b8330c402b375eb358446
<?php
// Test case
$input = [
['Value' => '390', 'Number' => 3],
['Value' => '804715', 'Number' => 4],
['Value' => 'WW001', 'Number' => 5],
['Value' => 'WHT/WHT/WHT', 'Number' => 6],
['Value' => '39/42', 'Number' => 7],
['Value' => '804715 WW00139/42', 'Number' => 8],
['Value' => '3pk Quarter Socks', 'Number' => 10],
];
$intersection = [];
foreach ($input as $config) {
$value = $config['Value'];
$number = $config['Number'];
$intersection[$number] = $value;
}
// Fill in the missing keys and use `null` as the value
$output = $intersection + array_fill_keys(range(1,10), null);
// Sort the final output by the keys
ksort($output);
// Format the keys to match FreeTextField{00}
$output = array_combine(
array_map(function($k){ return 'FreeTextField'.str_pad($k, 2, '0', STR_PAD_LEFT); }, array_keys($output)),
$output
);
// Use the extract function to bring all those array keys + values into the symbol table.
// You can now use $FreeTextField01 - $FreeTextField10
extract($output);
var_dump($output);
Use ${$var}
If you want to see a doc about this type of var you can see it here:
http://php.net/manual/en/language.variables.variable.php
I want to sort an existing array into 4 dimension array:
the "list" array that I have:
1 => "text1"
10 => "text10"
11 => "text11"
101 => "text101"
1011 => "text1011"
10123 => "text10123"
2 => "text2"
20 => "text20"
201 => "text201"
2011 => "text2011"
20111 => "text20111"
the array I want is one that has all the data sorted by each number (in 4 dimention) i mean that i won't have an other array in the end of $chapter[1] containing 10123 => "text10123" (this one will be in the same array as this one : 1011 => "text1011"
here is an exemple of the array i want
$chapter[1] = array(
1 => "text1", array(
10 => "text10", 11 => "text11", array(
101 => "text101", array(
1011 => "text1011", 10123 => "text10123" )
)
)
);
I guess you can use for-loop and break each number to digits (with str-split) and then add the arrays.
Consider the following example:
$arr = array(1, 11, 111, 113, 2, 21, 211, 213);
$chapter = array(); // this will be your result array
foreach($arr as $e) {
$digits = str_split($e);
$current = &$chapter;
foreach($digits as $d) {
if (!isset($current[$d]))
$current[$d] = array();
$current = &$current[$d];
}
}
Notice I used & to assign the new array to the original result one.
I know your array has missing key and not have to be sorted but I guess you can overcome it (filter and sort the array before)
Edited
After question has change this is the example code: (when key DATA is for the text you want and key CHILDREN for the next elements)
$arr = array(1 => "text1", 10 => "text10", 11 => "text11", 101 => "text101", 1011 => "text1011", 10123 => "text10123", 2 => "text2", 20 => "text20", 201 => "text201", 2011 => "text2011", 20111 => "text20111");
$chapter = array();
foreach($arr as $key => $val) {
$digits = str_split(substr($key, 0, 4)); // if 4 digits is the max depth
$current = &$chapter;
foreach($digits as $d) {
if (!isset($current["CHILDREN"][$d]))
$current["CHILDREN"][$d] = array();
$current = &$current["CHILDREN"][$d];
}
$current["DATA"] = $val;
}
This question already has answers here:
Add elements to array which has gapped numeric keys to form an indexed array / list
(5 answers)
Closed 5 months ago.
I have a following indexed array
$export_data = array (
[0] => 1,
[1] => 2,
[2] => 3,
[3] => 4,
[4] => 5,
[8] => 9,
[9] => 10,
);
I know how to export it to csv using fputcsv. However what my issue is that I need to export the data into correct column i.e. value in $export_data[8] needs to be exported in column 9 not column 6.
How can this be done please ?
Here you go, boss.
$export_data = array_replace(array_map(function($v){return null;}, range(0, max(array_keys($export_data)))), $export_data);
Tested 100,000 iterations and results are in seconds:
Version Run1 Run2 Run3
PHP 5.6.20 .58 .55 .50
PHP 7.0.5 .18 .21 .21
Now for the explanation so I don't get flogged with downvotes or get accused of witchcraft.
$export_data = array (
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5,
8 => 9,
9 => 10,
);
$export_data =
array_replace( // replace the elements of the 10-item array with your original array and the filled-in blanks are going to be null. I did not use array_merge() because it would append $export_data onto our dynamic range() array rather than replacing elements as needed.
array_map( // loop the 10-item array and apply the declared function per element. This function ends up returning the 10-item array with all keys intact but the values will be null
function($v){return null; /* return ''; // if you prefer and empty string instead of null*/}, // set each value of the 10-item array to null
range( // create an 10-item array with indexes and values of 0-9
0,
max(array_keys($export_data)) // get the highest key of your array which is 9
)
),
$export_data // your original array with gaps
);
var_dump($export_data);
print_r($export_data);
if i understand correctly, you want to put free columns between data, so the keys match column number.
$arr = array(
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5,
8 => 9,
9 => 10,
);
$csvArray = array();
$maxKey = max(array_keys($arr));
for($i = 0; $i <= $maxKey; $i++){
if(array_key_exists($i, $arr)){
$csvArray[$i] = $arr[$i];
} else {
$csvArray[$i] = null;
}
}
print_r($csvArray);
demo here: live demo
to describe it, just cycle through array and check wether key is set, if is, assing its value to the next array, if is not, assign null
Optimized:
$csvArray = array();
$maxKey = max(array_keys($arr));
// ++$i is microscopically faster when going for the long haul; such as 10,000,000 iterations
// Try it for yourself:
// $start = microtime(true);
// for($i=0; $i<10000000; $i++){}
// echo (microtime(true) - $start).' seconds';
for($i = 0; $i <= $maxKey; ++$i){
// we can use isset() because it returns false if the value is null anyways. It is much faster than array_key_exists()
$csvArray[$i] = (isset($arr[$i]) ? $arr[$i] : null);
}
I would just fill the array completely with empty values for the empty columns:
$export_data = array (
[0] => 1,
[1] => 2,
[2] => 3,
[3] => 4,
[4] => 5,
[5] => '',
[6] => '',
[7] => '',
[8] => 9,
[9] => 10,
);
Without the indexes (because they are automatic in any case):
$export_data = array (
1,
2,
3,
4,
5,
'',
'',
'',
9,
10,
);