Break array into chunks and prepend each row with a static element - php

I have the following array:
$list = array('item1','item2','item3','item4','item5','item6');
i need to take this array and break it into smaller arrays within 1 array for the csv. Each small array needs to have '999999' at index 0, followed by the next two items in the $list array. So the final result would be like this:
$newList = array(
array(999999, "item1" , "item2"),
array(999999, "item3" , "item4"),
array(999999, "item5" , "item6")
);
The original list array may contain up to 100 values at sometimes. What is the best way to achieve this?

Here's a different way of doing it, please see the comment as to where you place your additional elements to be prepended (you could add a second array into the merge at the end to add elements after the 2 list items too!)
See here for working example: http://codepad.org/hucpT5Yo
<?php
$list = array('item1','item2','item3','item4','item5','item6');
$list_chunks = array_chunk($list,2);
$list_chunks2 = array_map(
create_function(
'$x',
'return array_merge(array(
/* This array is prepended to the second,
add as many elements as you like */
999999,
"another element to add",
483274832
),
$x);'),
$list_chunks);
print_r($list_chunks2);
?>

$idx = 0;
$newarray = array();
$temparray = array('999999');
foreach($oldarray as $value) {
$temparray[] = $value;
if ((++$idx % 2)) == 0) {
$newarray[] = $temparray;
$temparray = array('999999');
}
}

Break your flat array into an array 2-element rows with array_chunk(), then call array_merge() on each row with the static value 999999 nested in an array and nominated as the first argument.
The modern syntax for the chunk-n-merge technique demonstrated by #Lee looks like this:
Code: (Demo)
$list = ['item1','item2','item3','item4','item5','item6'];
var_export(
array_map(fn($row) => array_merge([999999], $row), array_chunk($list, 2))
);
Output:
array (
0 =>
array (
0 => 999999,
1 => 'item1',
2 => 'item2',
),
1 =>
array (
0 => 999999,
1 => 'item3',
2 => 'item4',
),
2 =>
array (
0 => 999999,
1 => 'item5',
2 => 'item6',
),
)

Related

Move last array string to end of second last array string

I have an array like this:
$array = array(
0 => "a,b",
1 => "c,d",
2 => "e,f",
3 => "g,h",
);
I would like to merge the last two array elements (2 and 3) into a one like this:
$array = array(
0 => "a,b",
1 => "c,d",
2 => "e,f,g,h",
);
How can I do it using PHP?
Remove tow last items by array_splice and add implode of them
$temp = array_splice($array,-2);
$result = array_merge($array, (array) implode(',', $temp));
demo
As #Nick mentioned, you can do it by
$temp = array_splice($array,-2);
$array[] = implode(',', $temp);
Simple, use array_pop() to remove the last 2 elements, then concatenate them, then add them back to the original array.
$array = array(
0 => "a,b",
1 => "c,d",
2 => "e,f",
3 => "g,h",
);
$element3 = array_pop($array); //grab value of the last element, and remove it from the array.
$element2 = array_pop($array);
$array[] = "$element2,$element3";
this will always work if it's always supposed to be the last 2 elements.
This can be achieved with a one-liner that unconditionally pushes that joined strings of the last two elements after consuming them with array_splice(). In other words, the last two elements are removed, joined, then re-pushed into the array as a single element.
The $temp variable in #solash58's answer is not necessary -- the consumption of the last two elements will occur before the auto-incremented index is generated.
Code: (Demo)
$array = [
0 => "a,b",
1 => "c,d",
2 => "e,f",
3 => "g,h",
];
$array[] = implode(",", array_splice($array, -2));
var_export($array);
Output:
array (
0 => 'a,b',
1 => 'c,d',
2 => 'e,f,g,h',
)

Randomly select words from multi-dimension array

I have a multi-dimensional array and from where i want to choose 11 different words. Each word from different array index.
Here is the array link: My multi-dimensional array
array (
'w' =>
array (
0 => 'walls',
1 => 'well',
2 => 'why',
),
'e' =>
array (
0 => 'end',
),
'a' =>
array (
0 => 'advantage',
1 => 'afford',
2 => 'affronting',
3 => 'again',
4 => 'agreeable',
5 => 'ask',
6 => 'at',
),
'c' =>
array (
0 => 'children',
1 => 'civil',
2 => 'continual',
)
);
My Desire Output:
From w => well
From e => end
From a => again
and so on.
Output like: array(well, end, again, ...) as array.
Use the following code:
$f = array_keys($result); // grouping the indices, namely, the characters
$a = "";
for($c=0;$c<count($f);$c++){
$a .= $f[$c];
} // grouping the indices stored in array $f to a string, $a
$words = array();
for($c=0;$c<11;$c++){
$random = $a[rand(0,strlen($a)-1)];
$k = $result[$random];
// $k stores the array of the character index, stored in $result
$random2 = rand(0,count($k)-1);
$words[$c] = $k[$random2];
// choose a word from a given character array
$a = preg_replace("/".$random."/","",$a);
// remove the character from $a to prevent picking words which start with the same character
}
print_r($words);
I've tested and it was proved working
https://3v4l.org/qi1VP
You can achieve this usin array_rand() function :
PHP
$words = [];
$limit = 3; //Replace this with your limit, 11
$count = 0;
shuffle($array);
foreach($array as $key => $value) {
$words[] = $value[array_rand($value)];
$count++;
if ($limit == $count) {
break;
}
}
EvalIn
Check Online, and let me know.
using shuffle and array_slice you can get what you want.
A shuffle function makes your array random, and array slice slice 11 sub array from it.
Array slice takes 3 argument, first one is the array, second one is the offset from where you want to start and last one how much you need to cut.
$words = array();
shuffle($result);
$res = array_slice($result, 0, 11);
foreach($res as $key => $value){
shuffle($value);
$words[] = $value[0];
}
print_r($words);

PHP: take out duplicate digits from an array then print them out

I'm probably [super]overthinking this. I'm trying to analyze an array with values like [1,9], [4,6] [5,5], [6,4], [9,1] and duplicate digits (I'm having a super brain fart and can't even remember the term for numbers like this) remove (the last two) so that only [1,9], [4,6] [5,5] are printed.
I was thinking that turning this array into a string and using preg_match, but I'm pretty sure this wouldn't work even if I had the correct regex.
If you have an array of pairs like this:
$x = array(
array(1,9),
array(4,6),
array(5,5),
array(6,4),
array(9,1)
);
Here is one way to get the unique pairs:
foreach ($x as $pair) {
sort($pair);
$unique_pairs[implode(',', $pair)] = $pair;
}
This uses string representations of each sorted pair as keys in a new array, so the result will have distinct values by definition.
As far as the printing them out part of your question, once you have the unique values you can loop over them and print them out in whichever format you like, for example:
foreach ($unique_pairs as $pair) { vprintf("[%d,%d]<br>", $pair); }
It looks like elements are distributed symmetrically.
We can cut the array in two halves and get only the first half with array_slice():
$array = array(
array(1,9),
array(4,6),
array(5,5),
array(6,4),
array(9,1),
);
print_r(array_slice($array, 0, ceil(count($array) / 2)));
Result:
Array(
[0] => Array(
[0] => 1
[1] => 9
)
[1] => Array(
[0] => 4
[1] => 6
)
[2] => Array(
[0] => 5
[1] => 5
)
)
Demo at Codepad.
ceil() is used to round the number up to the next highest integer if there is an even number of items in the array. Example: if there is 3 items in the array, 5 / 2 will return 2.5, we want 3 items so we use ceil(2.5) which gives 3.
Example with 3 items:
$array = array(
array(1,9),
array(5,5),
array(9,1),
);
print_r(array_slice($array, 0, ceil(count($array) / 2)));
Result:
Array(
[0] => Array(
[0] => 1
[1] => 9
)
[1] => Array(
[0] => 5
[1] => 5
)
)
Example with 4 items:
$array = array(
array(1,9),
array(7,7),
array(7,7),
array(9,1),
);
print_r(array_slice($array, 0, ceil(count($array) / 2)));
Result:
Array(
[0] => Array(
[0] => 1
[1] => 9
)
[1] => Array(
[0] => 7
[1] => 7
)
)
If I'm correct in understanding what you are trying to do, you want to remove the final 2 elements from the array?
There is a function in PHP called array_pop that removes the final element from the array.
$array = array_pop($array);
So if you run this twice, you will remove the final 2 elements from the array.
This is how I'd do it (and I hope I am not overthinking this :))
$stringArray = array();
$stringArray[] = '1,9';
$stringArray[] = '4,6';
$stringArray[] = '5,5';
$stringArray[] = '6,4';
$stringArray[] = '9,1';
foreach($stringArray as &$numString) {
$numString = explode(',', $numString);
usort($numString, function($a, $b) {return $a - $b;});
$numString = implode(',', $numString);
}
$a = array_unique($a);
print_r($a);
You basically explode every element into a subarray, sort it and then implode it back. After calling the array_unique, you're left with unique values in the array.
The output would be
Array
(
[0] => 1,9
[1] => 4,6
[2] => 5,5
)
The result you suggest treats [a,b] as equivalent to [b,a] which makes the problem a lot more complex. The code below gives the result you asked for, but without really understanding what the problem is that you are trying to fix and whether [1,9] is equivalent to [9,1] in the solution:
$a=array(array(1,9),array(4,6),...
$dup=array();
for ($i=0; $i<count($a) -1; $i++) {
for ($j=$i+1; $j<count($a); $j++) {
if (($a[$i][0]==$a[$j[0] && $a[$i][1]==$a[$j[1])
|| ($a[$i][0]==$a[$j[1] && $a[$i][1]==$a[$j[0])) {
$dup[]=$j;
}
}
}
foreach ($dup as $i) {
unset($a[$i]);
}
So I'm actually going to assume your question to have a different meaning than everyone else did. I believe what you're asking is:
How do you filter out array items where a reverse of the item has already been used?
<?php
// The example set you gave
$numberSets = [[1, 9], [4, 6], [5, 5], [6, 4], [9, 1]];
// Initialize an empty array to keep track of what we've seen
$keys = [];
// We use array filter to get rid of items we don't want
// (Notice that we use & on $keys, so that we can update the variable in the global scope)
$numberSets = array_filter($numberSets, function($set) use(&$keys) {
// Reverse the array
$set = array_reverse($set);
// Create a string of the items
$key = implode('', $set);
// Get the reverse of the numbers
$reversedKey = strrev($key);
// If the palindrome of our string was used, return false to filter
if (isset($keys[$reversedKey])) {
return false;
}
// Set the key so it's not used again
// Since $keys is being passed by reference it is updated in global scope
$keys[$key] = true;
// Return true to NOT filter this item, since it or it's reverse were not matched
return true;
});
var_dump($numberSets);

Convert CSV string to Array keys and a value of 1 or true

Please could someone help find a better solution to the code below.
Here is my existing solution:
$list = '54,78,3,5';
$list = explode(",",$list);
foreach($list as $k => $v) { $compare[$v] = 1; }
when i run array_flip instead of the foreach on $list it returns an array like this:
Array(
54 => 0,
78 => 1,
...
)
I need this so another array which is already in this format can be compared with an IF statment:
Array(
54 => 1,
78 => 1,
...
)
$list = '54,78,3,5';
$list = explode(",",$list);
$array = array_combine($list, array_fill(0, count($list), 1));
print_r($array);
Array
(
[54] => 1
[78] => 1
[3] => 1
[5] => 1
)
array_fill() will create an array with all of its values being the number 1 at the same size as the $list array. array_combine() then creates a new array with the values of $list as the keys and the values created by array_fill();
Demo
Do you need the original $list to be a variable? Can't you just make it an array from the start wherever the data comes from, and append 1 or true to the value?
Otherwise, before your current foreach, add a new loop and go through $list (which you made into an array) and make a new array appending the required value to each key (keys taken from $list):
foreach ($list as $key)
{
$new_array[$key] = 1;
}

Multidimenssion array compare two arrays and update first array value

I want to filter a array by a number and update its status in the first array.
I have two array $arr1,$arr2
$arr1 = array(
0=>array('number'=>100,name=>'john'),
1=>array('number'=>200,name=>'johnny')
);
$arr2= array(
0=>array('number'=>300,name=>'r'),
1=>array('number'=>100,name=>'b'),
2=>array('number'=>200,name=>'c')
);
Final output should be an array like this
$arr1 = array(
0=>array('number'=>100,name=>'b'),
1=>array('number'=>200,name=>'c')
);
Any ideas to start off please ?
For specialized array modifications like this, the method of choice is array walk. It allows you to apply a custom function to each element in a given array.
Now, because of your data format, you will have to do a loop. Wrikken is asking if you can retrieve or transform the data to provide faster access. The algorithm below is O(n^2): it will require as many cycles as there are elements in the first array times the number of elements in the second array, or exactly count($arr1) * count($arr2).
function updateNameFromArray($element, $key, $arr2) {
foreach($arr2 as $value) {
if($value['number'] == $element['number']) {
$element['name'] == $value['name'];
break;
}
}
}
array_walk($arr1, "updateNameFromArray", $arr2);
Now, what Wrikken is suggesting is that if your arrays can be changed to be keyed on the 'number' property instead, then the search/replace operation is much easier. So if this were your data instead:
$arr1 = array(
100=>array('number'=>100,name=>'john'),
200=>array('number'=>200,name=>'johnny')
);
// notice the keys are 100 and 200 instead of 0,1
$arr2= array(
300=>array('number'=>300,name=>'r'),
100=>array('number'=>100,name=>'b'),
200=>array('number'=>200,name=>'c')
);
// notice the keys are 300, 100 and 200 instead of 0,1, 2
Then you could do this in O(n) time, with only looping over the first array.
foreach($arr1 as $key => $value) {
if(isset($arr2[$key])) {
$value['number'] = $arr2[$key]['number'];
}
}
Try this. It's not that clean but i think it would work.
<?php
$arr1 = array(0=>array('number'=>100,'name'=>'john'),1=>array('number'=>200,'name'=>'johnny'));
$arr2= array(0=>array('number'=>300,'name'=>'r'),1=>array('number'=>100,'name'=>'b'),2=>array('number'=>200,'name'=>'c'));
foreach( $arr1 as $key=>$data1 )
{
foreach( $arr2 as $key2=>$data2 )
{
if( $data1['number'] == $data2['number'] )
{
$arr1[$key]['name'] = $arr2[$key2]['name'];
}
}
}
print_r( $arr1 );
?>
the output would be :
Array
(
[0] => Array
(
[number] => 100
[name] => b
)
[1] => Array
(
[number] => 200
[name] => c
)
)
There isn't really a simple way for this to be accomplished with generic PHP functions, so, You might need to create mapping arrays.
The way I would approach this, is creating a loop that goes through the first array, and maps the number value as a key to the index of it's place in $arr1 giving you:
$tmp1 = array();
foreach ($arr1 as $key => $number_name) {
$tmp1[$number_name['number']] = $key;
}
This should give you an array that looks like
$tmp1 [
100 => 0,
200 => 1
];
Then I would loop through the second array, get the number value, if that existed as a key in $tmp1, get the associated value (being the key for $arr1), and use that to update the name in $arr1.
// Loop through $arr2
foreach ($arr2 as $number_name) {
// Get the number value
$number = $number_name['number'];
// Find the $arr1 index
if (isset($tmp1[$number])) {
$arr1_key = $tmp1[$number];
// Set the $arr1 name value
$arr1[$arr1_key]['name'] = $number_name['name'];
}
}
<?php
//Set the arrays
$arr1 = array(
array('number'=>100,'name'=>'john'),
array('number'=>200,'name'=>'johnny')
);
$arr2= array(
array('number'=>300,'name'=>'r'),
array('number'=>100,'name'=>'b'),
array('number'=>200,'name'=>'c')
);
// use a nested for loop to iterate and compare both arrays
for ($i=0;$i<count($arr1);$i++):
for ($j=0;$j<count($arr2);$j++):
if ($arr2[$j]['number']==$arr1[$i]['number'])
$arr1[$i]['name']=$arr2[$j]['name'];
endfor;
endfor;
print_r($arr1);
OUTPUT:
Array (
[0] => Array ( [number] => 100 [name] => b )
[1] => Array ( [number] => 200 [name] => c )
)
That being said, you should probably reconsider the very way your data is structured. Do you really need a multi-dimensional array or can you use a simple associative array, like so:
// set the arrays
$arr1 = array(
'john'=>100,
'johnny'=>200
);
$arr2 = array(
'r'=>300,
'b'=>100,
'c'=>200
);
// find values in arr2 common to both arrays
$arr3 = array_intersect($arr2, $arr1);
// change the key of arr1 to match the corresponding key in arr2
foreach ($arr3 as $key=>$value) {
$old_key = array_search($value, $arr1);
$arr1[$key]=$arr1[$old_key];
unset($arr1[$old_key]);
}
print_r($arr1);
OUTPUT:
Array (
[b] => 100
[c] => 200
)

Categories