Hello stackoverflow community. I need help with arrays. It's my weakness. I've got this kind of array:
Array
(
[0] => Array
(
[id] => 7
[slot] => 1
[name] => Apple
[start_date] => 12/16/2015
[end_date] => 03/10/2016
[status] => 1
[pre_exp_email] => 0
)
[1] => Array
(
[id] => 8
[slot] => 1
[name] => Cherry
[start_date] => 12/29/2015
[end_date] => 03/20/2016
[status] => 1
[pre_exp_email] => 0
)
[2] => Array
(
[id] => 5
[slot] => 3
[name] => Bananna
[start_date] => 11/30/2015
[end_date] => 00/00/0000
[status] => 1
[pre_exp_email] => 0
)
[3] => Array
(
[id] => 1
[slot] => 4
[name] => Kiwi
[start_date] => 11/21/2015
[end_date] => 12/21/2016
[status] => 1
[pre_exp_email] => 0
)
)
And my job is to randomize elements which has same [slot], but leave order ascending. For example now it is:
1 Apple 1 Cherry 3 Bannana 4 Kiwi
I need to randomize those elements who has same slot number. So Apple and Cherry would swap positions. How can I do this stuff?
Update : Using shuffle & usort :
shuffle($fruits);
function cmp($a, $b) {
if ($a['slot'] == $b['slot']) {
return 0;
}
return ($a['slot'] < $b['slot']) ? -1 : 1;
}
usort($fruits, "cmp");
Make a new array from the original having slot as keys
$elements = array(
0 => Array
(
'id' => 7,
'slot' => 1
),
1 => Array
(
'id' => 8,
'slot' => 1
),
2 => Array
(
'id' => 9,
'slot' => 1
),
3 => Array
(
'id' => 9,
'slot' => 5
)
);
foreach($elements as $element){
$newArray[$element['slot']][] = $element; //put every element having the same slot
}
$elementSlots = array_keys($newArray); // all slots are stored in elementSlots
$Result = array();
foreach($elementSlots as $slot) {
shuffle($newArray[$slot]); //randomize elements having the same slot
foreach($newArray[$slot] as $element) { //add them to the result array
$Result[$slot][] = $element;//For output 1
//$Result[] = $element; //For output 2
}
}
var_dump($Result);
Output 1:
array (size=2)
1 =>
array (size=3)
0 =>
array (size=2)
'id' => int 7
'slot' => int 1
1 =>
array (size=2)
'id' => int 9
'slot' => int 1
2 =>
array (size=2)
'id' => int 8
'slot' => int 1
5 =>
array (size=1)
0 =>
array (size=2)
'id' => int 9
'slot' => int 5
Output 2:
array (size=4)
0 =>
array (size=2)
'id' => int 7
'slot' => int 1
1 =>
array (size=2)
'id' => int 9
'slot' => int 1
2 =>
array (size=2)
'id' => int 8
'slot' => int 1
3 =>
array (size=2)
'id' => int 9
'slot' => int 5
I have a multidimensional array that looks like this:
Array (
[0] => Array (
[date] => August
[mozrank] => 2
[domain_authority] => 41
[external_links] => 9
[unique_visitors] => 14
)
[1] => Array (
[date] => August
[post_count] => 70
[comment_count] => 53
[theme] => yes
[plugins] => 3
)
[2] => Array (
[date] => September
[mozrank] => 4
[domain_authority] => 42
[external_links] => 10
[unique_visitors] => 20
)
[3] => Array (
[date] => September
[post_count] => 71
[comment_count] => 56
[theme] => yes
[plugins] => 5
)
)
You'll notice that there are two arrays that have the same key/value pair of August and two arrays that have the same key/value pair of September. However in each case they have different keys associated with them. I'm trying to group each array on the date key where the value is the same and merge the other keys together. For example, the output would be:
Array (
[0] => Array (
[date] => August
[mozrank] => 2
[domain_authority] => 41
[external_links] => 9
[unique_visitors] => 14
[post_count] => 70
[comment_count] => 53
[theme] => yes
[plugins] => 3
)
[1] => Array (
[date] => September
[mozrank] => 4
[domain_authority] => 42
[external_links] => 10
[unique_visitors] => 20
[post_count] => 71
[comment_count] => 56
[theme] => yes
[plugins] => 5
)
)
Any ideas?
First thing that cross my mind:
$merged = array();
foreach ($array as $item)
{
$date = $item['date'];
if (!isset($merged[$date]))
{
$merged[$date] = array();
}
$merged[$date] = array_merge($merged[$date], $item);
}
As result there will be an array where key is a month. If you want standard index (begin from 0) you can always use shuffle().
Result:
array (size=2)
'August' =>
array (size=9)
'date' => string 'August' (length=6)
'mozrank' => int 2
'domain_authority' => int 41
'external_links' => int 9
'unique_visitors' => int 14
'post_count' => int 70
'comment_count' => int 53
'theme' => string 'yes' (length=3)
'plugins' => int 3
'September' =>
array (size=9)
'date' => string 'September' (length=9)
'mozrank' => int 4
'domain_authority' => int 42
'external_links' => int 10
'unique_visitors' => int 20
'post_count' => int 71
'comment_count' => int 56
'theme' => string 'yes' (length=3)
'plugins' => int 5
P.S. I have feeling that it can be done better than this...
i have two arrays and i need to extract the values of the 2nd array depending on the value of $arr[0]["num"]
$arr = array(
0 => array(
"id" => 24,
"num" => 2
),
1 => array(
"id" => 25,
"num" => 5
)
2 => array(
"id" => 26,
"num" => 3
)
);
$array = array('1','2','3','4','5','6','7','8','9','10');
$new = array();
foreach($arr as $key){
for($i=0;$i<$key['num'];$i++){
$new[$key['id']][$i] = $array[$i];
}
}
is it possible to remove the values of the 2nd array and transfer it into a new array?
what my loop does is just copying the values from the start after each loop. i want to remove the copied values from the 2nd array.
The output should be like this:
Array
(
[24] => Array
(
[0] => 1
[1] => 2
)
[25] => Array
(
[0] => 3
[1] => 4
[2] => 5
[3] => 6
[4] => 7
)
[26] => Array
(
[0] => 8
[1] => 9
[2] => 10
)
)
I'd suggest using array_shift
$arr = array(
array(
"id" => 24,
"num" => 2
),
array(
"id" => 25,
"num" => 5
),
array(
"id" => 26,
"num" => 3
)
);
$array = array('1','2','3','4','5','6','7','8','9','10');
$new = array();
foreach($arr as $key){
for($i=0;$i<$key['num'];$i++){
$new[$key['id']][$i] = $array[0]; // *1
array_shift($array);
}
}
echo '<pre>';
print_r($new);
*1 You have to change this line as well. Since array_shift removes the first array entry, each iteration should access array[0].
Output:
Array
(
[24] => Array
(
[0] => 1
[1] => 2
)
[25] => Array
(
[0] => 3
[1] => 4
[2] => 5
[3] => 6
[4] => 7
)
[26] => Array
(
[0] => 8
[1] => 9
[2] => 10
)
)
Try this
foreach($arr as $key){
for($i=0;$i<$key['num'];$i++){
$new[$key['id']][$i] = $array[$i];
// unset previous values, in first iteration it will remove 0, 1
unset($array[$i]);
}
// reset the array keys, so for loop $i will start from 0
$array = array_values($array);
}
Output:
array (size=3)
24 =>
array (size=2)
0 => string '1' (length=1)
1 => string '2' (length=1)
25 =>
array (size=5)
0 => string '3' (length=1)
1 => string '4' (length=1)
2 => string '5' (length=1)
3 => string '6' (length=1)
4 => string '7' (length=1)
26 =>
array (size=3)
0 => string '8' (length=1)
1 => string '9' (length=1)
2 => string '10' (length=2)
here's my array
Array
(
[0] => Array
(
[0] => Jan 2010
[1] => 65.75
)
[1] => Array
(
[0] => Jan 2010
[1] => 211.05
)
[2] => Array
(
[0] => Jan 2010
[1] => 582.7
)
[3] => Array
(
[0] => Feb 2010
[1] => 136.3
)
[4] => Array
(
[0] => Feb 2010
[1] => 215.32
)
[5] => Array
(
[0] => Feb 2010
[1] => 413.9
)
[6] => Array
(
[0] => Mar 2010
[1] => 156.35
)
[7] => Array
(
[0] => Mar 2010
[1] => 210.54
)
[8] => Array
(
[0] => Mar 2010
[1] => 585.15
)
[9] => Array
(
[0] => Apr 2010
[1] => 126.1
)
[10] => Array
(
[0] => Apr 2010
[1] => 255.47
)
[11] => Array
(
[0] => Apr 2010
[1] => 329.1
)
[12] => Array
(
[0] => May 2010
[1] => 109
)
[13] => Array
(
[0] => May 2010
[1] => 170
)
[14] => Array
(
[0] => May 2010
[1] => 716.7
)
)
is there any way I can make all arrays with the same value in [0] merge? i want it to be something like this:
Array[0] = (Jan 2010, 65.75, 211.05, 582.7)
Array[1] = (Feb 2010, 136.3, 215.32, 413.9)
and so on...
The closest I can think to do this "simply" (read: taking advantage of native PHP features) is switching to text keys (associative array) for your result. This makes sense from a data modeling perspective as well, since in your sample result arrays you are mixing "key" data and "value" data (e.g. the first value carries the responsibility of being the label for the set == bad). The trick is to use the implicit "push" operator [], which appends a new value to an array.
foreach($sourceArray as $currentSubArray) {
$resultArray[$currentSubArray[0]][] = $currentSubArray[1];
}
Your result will look like this:
Array (
'Jan 2010' => Array (
0 => 65.75,
1 => 211.05,
2 => 582.7,
)
...
)
This is a variant of what #ctrahey suggested, that operates on the input array directly:
foreach($array as $key => &$entry) {
list($month, $value) = $entry;
if (isset($ptr[$month])) {
$ptr[$month][] = $value;
unset($array[$key]);
} else {
$ptr[$month] = &$entry;
}
}
unset($ptr);
Output with your example data:
Array
(
[0] => Array
(
[0] => Jan 2010
[1] => 65.75
[2] => 211.05
[3] => 582.7
)
[3] => Array
(
[0] => Feb 2010
[1] => 136.3
[2] => 215.32
[3] => 413.9
)
[6] => Array
(
[0] => Mar 2010
[1] => 156.35
[2] => 210.54
[3] => 585.15
)
[9] => Array
(
[0] => Apr 2010
[1] => 126.1
[2] => 255.47
[3] => 329.1
)
[12] => Array
(
[0] => May 2010
[1] => 109
[2] => 170
[3] => 716.7
)
)
actionMerge($inputArray);
function actionMerge($inputArray){
$month = array();
$earn = array();
$parentKey = 0;
$callback = function ($value, $key) use (&$month, &$earn, &$parentKey) {
if(!is_array($value)){
if($key == 0){
if(!in_array($value, $month)){
array_push($month, $value);
$earn[$value] = array();
}
$parentKey = $value;
}elseif($key == 1){
array_push($earn[$parentKey], $value);
}
}
};
array_walk_recursive($inputArray, $callback);
echo 'You should use this array';
var_dump($earn); // group money by month, I recommend you to use it
$Array = array();
foreach($month as $m){
$arr = array($m);
$arr = array_merge($arr, $earn[$m]);
array_push($Array, $arr);
}
echo '...Intead of array result what you expect';
var_dump($Array); // your expect result
}
?>
Here is result:
//You should use this array
array (size=5)
'Jan 2010' =>
array (size=3)
0 => float 65.75
1 => float 211.05
2 => float 582.7
'Feb 2010' =>
array (size=3)
0 => float 136.3
1 => float 215.32
2 => float 413.9
'Mar 2010' =>
array (size=3)
0 => float 156.35
1 => float 210.54
2 => float 585.15
'Apr 2010' =>
array (size=3)
0 => float 126.1
1 => float 255.47
2 => float 329.1
'May 2010' =>
array (size=3)
0 => int 109
1 => int 170
2 => float 716.7
//...Intead of array result what you expect
array (size=5)
0 =>
array (size=4)
0 => string 'Jan 2010' (length=8)
1 => float 65.75
2 => float 211.05
3 => float 582.7
1 =>
array (size=4)
0 => string 'Feb 2010' (length=8)
1 => float 136.3
2 => float 215.32
3 => float 413.9
2 =>
array (size=4)
0 => string 'Mar 2010' (length=8)
1 => float 156.35
2 => float 210.54
3 => float 585.15
3 =>
array (size=4)
0 => string 'Apr 2010' (length=8)
1 => float 126.1
2 => float 255.47
3 => float 329.1
4 =>
array (size=4)
0 => string 'May 2010' (length=8)
1 => int 109
2 => int 170
3 => float 716.7
It's quite horrible,but it works...
$resarray=Array(
0 => Array(0 => 'Jan 2010',1 => 65.75),
1=> Array(0 => 'Jan 2010',1 => 211.05),
2 => Array(0 => 'Jan 2010',1 => 582.7),
3 => Array(0 => 'Feb 2010',1 => 136.3),
4 => Array(0 => 'Feb 2010',1 => 215.32),
5 => Array(0 => 'Feb 2010',1 => 413.9),
6 => Array(0 => 'Feb 2010',1 => 156.35),
7 => Array(0 => 'Feb 2010',1 => 210.54),
8 => Array(0 => 'Mar 2010',1 => 585.15),
9 => Array(0 => 'Apr 2010',1 => 126.1),
10 => Array(0 => 'Apr 2010',1 => 255.47),
11 => Array(0 => 'Apr 2010',1 => 329.1),
12 => Array(0 => 'May 2010',1 => 109),
13 => Array(0 => 'May 2010',1 => 170),
14 => Array(0 => 'May 2010',1 => 716.7)
);
$CatArray=array();
$FinArray=array();
$count=count($resarray);
for($i=0;$i<$count;$i++){
$index=array_search($resarray[$i][0],$CatArray);
if(is_numeric($index) && $index>=0)
$FinArray[$index][]=$resarray[$i][1];
else{
$CatArray[]=$resarray[$i][0];
$FinArray[]=array($resarray[$i][0],$resarray[$i][1]);
}
}
unset($CatArray);
unset($resarray);
$count=count($FinArray);
for($i=0;$i<$count;$i++){
$resarray[$i]=implode(',',$FinArray[$i]);
}
Output:
Array
(
[0] => Jan 2010,65.75,211.05,582.7
[1] => Feb 2010,136.3,215.32,413.9,156.35,210.54
[2] => Mar 2010,585.15
[3] => Apr 2010,126.1,255.47,329.1
[4] => May 2010,109,170,716.7
)
I have here a nested multidimensional array:
Array
(
[merchant] => Array
(
[XML_Serializer_Tag] => Array
(
[id] => 736
[name] => Cadbury Gifts Direct
)
[prod] => Array
(
[XML_Serializer_Tag] => Array
(
[0] => Array
(
[XML_Serializer_Tag] => Array
(
[id] => 88966064
[pre_order] => no
[web_offer] => no
[in_stock] => no
[stock_quantity] => 0
)
[pId] => 608
[isbn] => 0000000000000
[text] => Array
(
[name] => 50% OFF 56g Creme Egg Minis
[desc] => 50% OFF Creme Egg Minis in a 56g bag.
)
[uri] => Array
(
[awTrack] => http://www.awin1.com/pclick.php?p=88966064&a=67702&m=736
[awThumb] => http://images.productserve.com/thumb/736/88966064.jpg
[awImage] => http://images.productserve.com/preview/736/88966064.jpg
[mLink] => http://www.cadburygiftsdirect.co.uk/products/608-50-off-56g-creme-egg-minis.aspx
[mImage] => http://www.cadburygiftsdirect.co.uk/images/thumbs/0001084.png
)
[price] => Array
(
[XML_Serializer_Tag] => Array
(
[curr] => GBP
)
[buynow] => 0.31
[store] => 0.00
[rrp] => 0.00
[delivery] => 0.00
)
[cat] => Array
(
[awCatId] => 437
[awCat] => Chocolate
[mCat] => Full Range
)
[brand] =>
[valFrom] => 0000-00-00
[valTo] => 0000-00-00
[comAmount] => 0.00
)
The segment loop afterwards.
So...
[1] => Array
[2] => Array
[3] => Array
etc...
I need to find the names of the attributes of each array segment.
So I have used this recursive loop:
private function recursive_array($old_array, $new_array = array()) {
foreach ($old_array as $key => $value) {
if (is_array($value) && $key < 1) {
$new_array = $this->recursive_array($value, $new_array);
} else {
if ($key < 1) {
$new_array[] = $key;
}
}
}
return $new_array;
}
This is the output:
array
0 => string 'id' (length=2)
1 => string 'name' (length=4)
2 => string 'id' (length=2)
3 => string 'pre_order' (length=9)
4 => string 'web_offer' (length=9)
5 => string 'in_stock' (length=8)
6 => string 'stock_quantity' (length=14)
7 => string 'pId' (length=3)
8 => string 'isbn' (length=4)
9 => string 'name' (length=4)
10 => string 'desc' (length=4)
11 => string 'awTrack' (length=7)
12 => string 'awThumb' (length=7)
13 => string 'awImage' (length=7)
14 => string 'mLink' (length=5)
15 => string 'mImage' (length=6)
16 => string 'curr' (length=4)
17 => string 'buynow' (length=6)
18 => string 'store' (length=5)
19 => string 'rrp' (length=3)
20 => string 'delivery' (length=8)
21 => string 'awCatId' (length=7)
22 => string 'awCat' (length=5)
23 => string 'mCat' (length=4)
24 => string 'brand' (length=5)
25 => string 'valFrom' (length=7)
26 => string 'valTo' (length=5)
27 => string 'comAmount' (length=9
What it is also picking up is the top nested array:
[XML_Serializer_Tag] => Array
(
[id] => 736
[name] => Cadbury Gifts Direct
)
This is just details for the entire feed not the individual segments.
I need a way of filtering out the top nested array but bear in mind that the details are dynamic so the name of the keys can change from one feed to the next
Maybe this?
$riter = new RecursiveIteratorIterator(New RecursiveArrayIterator($array));
foreach ($riter as $key => $val) {
if ($riter->getDepth() > 1) {
echo "$key => $val\n";
}
}
by default, RecursiveIteratorIterator only visits leaf nodes(the deepest levels down every path). getDepth() can be used to make sure were a minimum depth. I'm not sure if 1 is the correct number, but anyway...
use array_shift to pop off the first element of the array