php function to split array into 3 parts with out leaving remainders - php

I have an simple array that I would like split into 3 random rows.
So far I am using the array chunk function which successful splits it into 3 rows, but because the array count is uneven, it spilts the array into 3 rows but leaves a remainder 2 values in a 4th row. See code below...
<?php
$my_bikes = array (
'bike-996.png',
'bike-adventure.png',
'bike-bandit.png',
'bike-blade.png',
'bike-classic-racer.png',
'bike-classic-rm.png',
'bike-custom.png',
'bike-dragster.png',
'bike-ducati-scrambler.png',
'bike-electric-concept.png',
'bike-flat-tracker.png',
'bike-goldwing.png',
'bike-gsx.png',
'bike-harley.png',
'bike-indian-vintage.png',
'bike-kiddimoto.png',
'bike-livewire.png',
'bike-lotus.png',
'bike-monkey-bike.png',
'bike-moto3.png',
'bike-mx.png',
'bike-rc.png',
'bike-rc213v.png',
'bike-roland-sands.png',
'bike-scooter.png',
'bike-speedway.png',
'bike-tron.png',
'bike-vespa.png',
'bike-vision.png',
);
shuffle($my_bikes);
// chunk my bike
$my_bikes = array_chunk($my_bikes, count($my_bikes) / 3);
?>
<?php foreach($my_bikes as $key => $my_bike_row) : ?>
<div class="row <?=$key % 2==0 ? 'left' : 'right' ?>">
<?php foreach($my_bike_row as $my_bike): ?>
<img src="<?=get_path('images/bikes/' . $my_bike)?>" alt="">
<?php endforeach; ?>
</div>
<?php endforeach; ?>
<?=exit( '<pre>' . print_r( $my_bikes, true ));?>
See my current output below...
Array
(
[0] => Array
(
[0] => bike-roland-sands.png
[1] => bike-monkey-bike.png
[2] => bike-classic-rm.png
[3] => bike-classic-racer.png
[4] => bike-vespa.png
[5] => bike-rc213v.png
[6] => bike-flat-tracker.png
[7] => bike-dragster.png
[8] => bike-custom.png
)
[1] => Array
(
[0] => bike-speedway.png
[1] => bike-blade.png
[2] => bike-tron.png
[3] => bike-indian-vintage.png
[4] => bike-harley.png
[5] => bike-goldwing.png
[6] => bike-kiddimoto.png
[7] => bike-livewire.png
[8] => bike-moto3.png
)
[2] => Array
(
[0] => bike-adventure.png
[1] => bike-mx.png
[2] => bike-rc.png
[3] => bike-scooter.png
[4] => bike-996.png
[5] => bike-gsx.png
[6] => bike-ducati-scrambler.png
[7] => bike-lotus.png
[8] => bike-electric-concept.png
)
[3] => Array
(
[0] => bike-vision.png
[1] => bike-bandit.png
)
)
As you can see, I'm left with 4 rows.
My question is, what method is there with PHP where I can split the array into 3 rows, but if its an uneven number (as per my example) that the last the remainders are included the in the 3 rows, and not left remainding.
I don't wan't any duplicates ideally.
Thanks

Use array_chunk()
And calculate the size by rounding up the fraction(if any) to next highest integer value by ceil(count($my_bikes)/3)
So in this case - count($my_bikes)/3 => 26/3 => 8.66.
ceil(8.66) => 9
The chunk sizes will be 9, 9, 8
array_chunk($my_bikes, (ceil(count($my_bikes)/3)))

array_chunk($my_bikes,(count($my_bikes)/3)+1);

Related

PHP Array delete an entire array by one element value

So this is how my Array ($dataArray) looks oks like:
Array
(
[0] => Array
(
[0] => Date
[1] => Time
[2] => Duration
[3] => Info
[4] => Client
)
[1] => Array
(
[0] => 2021-12-01
[1] => 10:45:43
[2] => 237
[3] => Some text from
[4] => Client 1
)
[2] => Array
(
[0] => 2021-12-01
[1] => 11:29:13
[2] => 77
[3] => Nothing important
[4] => Client 2
)
[3] => Array
(
[0] => 2021-12-01
[1] => 11:53:03
[2] => 44
[3] => anonymous
[4] => Client 1
)
I need to Loop trough it to search the Client Names, and if i find the matching name in the Element 4 then delete the entire Array.
$ExportKDname = "Client 1"
foreach($dataArray as $key => $sub_array) {
if($sub_array[4] == $ExportKDname) {
unset($dataArray[$key]);
break;
}
}
print_r($dataArray);
But with this code none of the arrays will be deleted. And I just can not find the right way to do it.
The Final array what I need to look like if we find the "Client 1" in the array would be like this:
Array
(
[0] => Array
(
[0] => Date
[1] => Time
[2] => Duration
[3] => Info
[4] => Client
)
[1] => Array
(
[0] => 2021-12-01
[1] => 11:29:13
[2] => 77
[3] => Nothing important
[4] => Client 2
)
In the if condition you are saying "if u match with $sub_arr[4] == $ExportKDname unset it and stop the loop". the machine doing that. when it matched first time it removes and stoping. If u wanna delete all match do not write break; let it continue. So delete or make it comment break; line.
You can array_filter your variable and check if value is in_array.
With PHP 7.4+ syntax it should look like this:
$result = array_filter($dataArray, fn ($innerArray) => !in_array('Client 1', $innerArray));

PHP - Converting Array to group duplicates together - phpspreadsheet

I have a csv uploader i'm creating to push to an order api. Using phpSpreadsheets toArray method, i have an array like so:
Array
(
[0] => Array
(
[0] => product_sku
[1] => product_qty
[2] => shipping_name
[3] => shipping_address1
[4] => shipping_address2
[5] => shipping_city
[6] => shipping_county
[7] => shipping_postcode
[8] => shipping_type
[9] => customer_id
)
[1] => Array
(
[0] => test_sku_1
[1] => 3
[2] => Bruce Wayne
[3] => The Manor
[4] => Near Arkahm Asylumn
[5] => Gotham
[6] => Greater Gothan
[7] => B17MAN
[8] => 1
[9] => 14994333
)
[2] => Array
(
[0] => test_sku_2
[1] => 2
[2] => Bruce Wayne
[3] => The Manor
[4] => Near Arkahm Asylumn
[5] => Gotham
[6] => Greater Gothan
[7] => B17MAN
[8] => 1
[9] => 14994333
)
[3] => Array
(
[0] => test_sku_3
[1] => 7
[2] => Bruce Wayne
[3] => The Manor
[4] => Near Arkahm Asylumn
[5] => Gotham
[6] => Greater Gothan
[7] => L17MA2
[8] => 1
[9] => 14994333
)
)
Each order will be on a new line, however if a customer orders two different items, i need to group them together using their postcode. As such i was aiming to rearange into this format:
[orders] => Array(
Array(
[shipping_name] => "Bruce wayne",
[customer_id] => 14994333,
[address] => Array(
[shipping_address1] => "The Manor",
[shipping_address2] => "Near Arham Asylumn",
[shipping_city] => "Gotham",
[shipping_county] => "Greater Gotham",
[shipping_postcode] => "B17MAN",
)
[products] => Array(
Array(
[sku] => "test_sku_1",
[quantity] => 3
),
Array(
[sku] => "test_sku_2",
[quantity] => "2"
)
)
)
)
Once of the first problems i encountered was trying to match the postcodes. I managed to get a count using:
$getDuplicates = array_count_values(array_map(function($duplicates) {
return $duplicates[7]; //Where 7 is the postcode
}, $rows));
This worked in counting what i needed correctly. However from there i'm hitting a brick wall. If i'm counting the duplicates, i need it to also make a note of the rows it's already gone through so they aren't pushed incorrectly into the new array i want to make.
Pseudo it should be:
for each rows as row{
if row isn't set to be ignored{
for each count of this postcode{
array_push the product sku and qty
mark these rows as rows to be ignored
}
}
}
Can anyone help me with this?
So, long story short, i've been so caught up in this i completely missed the obvious. To solve this, i took the original array from phpspreadsheet and did an array_multisort:
foreach ($rows as $key => $row) {
$postcodes[$key] = $row[7]; //the postcode key
}
array_multisort($postcodes, SORT_DESC, $rows;
I then just worked my way through the array and if the postcode changed, i'd create a new array, otherwise i'd just push straight into the correct array for the products.
I feel really stupid i didn't think of this before. Thank you to #apokryfos for trying to help!

Reorganise array, move indexes to specific locations php

I have an arbitrary number of arrays all containing the same format of data. There are 2 separate for loops looping through two separate SQL query results and adding them to 2 separate arrays.
Once I have all the information in both arrays, I am walking through them and joining them together to make a longer array.
However, as I am writing this array to a csv file, The information needs to be in order in the array so it writes it in order to the csv file. How can I do this?
Array 1
[1] => Array
(
[0] => 2017-07-21 00:00:00
[1] => Foo
[2] => Bar
[3] => 32.63
[4] => 18.36
[5] => 98.46
)
[2] => Array
(
[0] => 2017-07-21 00:00:00
[1] => Foo
[2] => Bar
[3] => 29.74
[4] => 148.68
[5] => 178.42
)
//etc
Array 2
[1] => Array
(
[0] => RTGH707321222
[1] => THIS
[2] => IS
[3] => TEXT
)
[2] => Array
(
[0] => RTGH707321220
[1] => SOME
[2] => WORDS
[3] => HERE
)
//etc
Joining the arrays together
array_walk($array2, function($values, $key) use (&$array1) {
$array1[$key] = array_merge($array1[$key], $values);
} );
After The array Merge - print_r($array1)
[1] => Array
(
[0] => 2017-07-21 00:00:00
[1] => Foo
[2] => Bar
[3] => 32.63
[4] => 18.36
[5] => 98.46
[6] => RTGH707321222
[7] => THIS
[8] => IS
[9] => TEXT
)
[2] => Array
(
[0] => 2017-07-21 00:00:00
[1] => Foo
[2] => Bar
[3] => 29.74
[4] => 148.68
[5] => 178.42
[6] => RTGH707321220
[7] => SOME
[8] => WORDS
[9] => HERE
)
//etc
So this is working fine. However, I would like to move some of these indexes around so that they are in a different order. I have looked into array_splice() but I am not sure if this is the correct method to use.
What I want it to look like
[1] => Array
(
[0] => 2017-07-21 00:00:00
[1] => RTGH707321222
[2] => TEXT
[3] => THIS
[4] => 18.36
[5] => 98.46
[6] => Foo
[7] => 32.63
[8] => IS
[9] => Bar
)
//etc
As you can see, all the information is still the same. The values have just been moved to different indexes. How can I sort the array so that it looks like the above. Can anyone point me in the right direction? Thanks.
This is a simpler method using array_replace() and an ordering array.
No extra loop, no temporary swapping variables.
Code: (Demo)
$array1=[
1=>['2017-07-21 00:00:00','Foo','Bar',32.63,18.36,98.46],
2=>['2017-07-21 00:00:00','Foo','Bar',29.74,148.68,178.42]
];
$array2=[
1=>['RTGH707321222','THIS','IS','TEXT'],
2=>['RTGH707321220','SOME','WORDS','HERE']
];
$order=[0=>'',6=>'',9=>'',7=>'',4=>'',5=>'',1=>'',3=>'',8=>'',2=>''];
array_walk($array2, function($values, $key) use (&$array1,$order) {
$array1[$key] = array_replace($order,array_merge($array1[$key], $values));
});
var_export($array1);
we can use swap technice here like,
<?php
foreach ($arr as $key => $value) {
$swap = $value[1];
$arr[$key][1] = $value[6];
$arr[$key][6] = $swap;
$swap = $value[9];
$arr[$key][9] = $value[2];
$arr[$key][2] = $swap;
$swap = $value[7];
$arr[$key][7] = $value[3];
$arr[$key][3] = $swap;
}
print_r($arr);
?>
$arr is your array.

Getting data from an object array

I have an array
Array (
[bla123] => Array
(
[0] => 2
[1] => 3
[2] => 2
[3] => 2
[4] => 2
[5] => 2
[6] => 2
[7] => 2
[8] => 2
)
[12xye] => Array
(
[0] => 4
[1] => 3
[2] => 3
[3] => 2
[4] => 2
[5] => 4
[6] => 2
[7] => 2
[8] => 2
)
)
How can i access this array in php and also get the number of 1,2,3.. etc from it in php.
The logic is to get the rating of a products. the data is fetched from the database completely and then sorted using php.
for eg:
product1
one star:1
two star:3
three star:2
etc...
somewhat like a star system in flipkart, amazons etc..
use the below code:
<?php
$mainArrDat = array('bla123'=>array('Your_Array_Data_Here'),'12xye'=>('Your_Array_Data_Here'));
foreach( $mainArrDat as $mainArr )
{
foreach($mainArr as $nowArr)
{
//you can access the data that you require from $nowArr
}
}
?>

How to match an optional subpattern in the middle or end of an url depending on the existence of a filename and extension

I am trying to preg_match a url consisting of a category slug, an optional subcategory slug and an option item slug.
It works in all cases, except for the 4th case.
$urls[0] = '/main_cat_slug';
$urls[1] = '/main_cat_slug/';
$urls[2] = '/main_cat_slug/sub_cat_slug';
$urls[3] = '/main_cat_slug/sub_cat_slug/';
$urls[4] = '/main_cat_slug/item.html';
$urls[5] = '/main_cat_slug/sub_cat_slug/item.html';
$regexp = array();
$regexp[] = '/(?:(?<category>[\w]+)/?)'; // Find the main category (is always available)
$regexp[] = '(?:(?<subcategory>[\w]+)/?)?'; // Find an optional sub-category, is not always available
$regexp[] = '(?:(?<item>[\w]+)\.html)?'; // Find an optional item, is not always available (don't catch the extension)
$regexp = implode('', $regexp);
foreach($urls as $index=>$url) {
preg_match("#{$regexp}#i", $url, $matches);
echo '<pre><h1>', $index, '</h1>';
echo $url, '<br />';
echo '<br />';
print_r($matches);
}
In the 4-th case, the category will be found, but the item is empty and the subcategory gets the value op "item".
Could someone help me out, so that the 4-th case will only get a category and an item?
This is the output for above code:
0
/main_cat_slug
Array
(
[0] => /main_cat_slug
[category] => main_cat_slug
[1] => main_cat_slug
)
1
/main_cat_slug/
Array
(
[0] => /main_cat_slug/
[category] => main_cat_slug
[1] => main_cat_slug
)
2
/main_cat_slug/sub_cat_slug
Array
(
[0] => /main_cat_slug/sub_cat_slug
[category] => main_cat_slug
[1] => main_cat_slug
[subcategory] => sub_cat_slug
[2] => sub_cat_slug
)
3
/main_cat_slug/sub_cat_slug/
Array
(
[0] => /main_cat_slug/sub_cat_slug/
[category] => main_cat_slug
[1] => main_cat_slug
[subcategory] => sub_cat_slug
[2] => sub_cat_slug
)
4
/main_cat_slug/item.html
Array
(
[0] => /main_cat_slug/item
[category] => main_cat_slug
[1] => main_cat_slug
[subcategory] => item
[2] => item
)
5
/main_cat_slug/sub_cat_slug/item.html
Array
(
[0] => /main_cat_slug/sub_cat_slug/item.html
[category] => main_cat_slug
[1] => main_cat_slug
[subcategory] => sub_cat_slug
[2] => sub_cat_slug
[item] => item
[3] => item
)
Kind regards!
Patrick
Description
This regex will pickout the three types of data, using the following rules:
The / is always the first character in the string
The Main_Cat is always first, it follows the first / and continues until the next /
If the first string ends in .html/ then this is a Main_Cat
if the first string ends in .html followed by the end of the string, then this is an item
The Sub_Cat is always second, it follows the second / and continues until the next /
If the second string ends in .html/ then this is a Sub_Cat
if the second string ends in .html followed by the end of the string, then this is an item
The Item type always has an .html suffix
There will never be a / after the Item
the Item type will always be the last field
^\/(?:(?<Main_Cat>(?![^\/\r\n]*\.html\s*$)[^\/\r\n]*)\/)?(?:(?<Sub_Cat>(?![^\/\r\n]*\.html\s*$)[^\/\r\n]*)\/)?(?:(?<Item>[^\/\r\n]*?)(?:\.html|$))?
If you're using this expression against individual strings then you can remove the new line characters \r\n. The resulting expression would look like: ^\/(?<Main_Cat>[^\/]*)(?:(?:\/(?![^\/]*\.html)(?<Sub_Cat>[^\/]*))?(?:\/(?<Item>[^\/]*)\.html)?)?.*?$ follows the same rules above. Note the end of line $ forces the test to match your entire string
PHP Code Example:
Source String
/category0.html/subcat/item.html
/item1.html
/category2.html/subcat2.html/item2.html
/category3.html/subcat3.html/
/category4.html/item4.html
/main_cat_slug5.html/
/main_cat_slug6/item6
/main_cat_slug7/sub_cat_slug7.html/
/main_cat_slug8/item8.html
/main_cat_slug9/sub_cat_slug9/item9.html
Code
<?php
$sourcestring="your source string";
preg_match_all('/^\/(?:(?<Main_Cat>(?![^\/\r\n]*\.html\s*$)[^\/\r\n]*)\/)?(?:(?<Sub_Cat>(?![^\/\r\n]*\.html\s*$)[^\/\r\n]*)\/)?(?:(?<Item>[^\/\r\n]*?)(?:\.html|$))?/imx',$sourcestring,$matches);
echo "<pre>".print_r($matches,true);
?>
Matches
$matches Array:
(
[0] => Array
(
[0] => /category0.html/subcat/item.html
[1] => /item1.html
[2] => /category2.html/subcat2.html/item2.html
[3] => /category3.html/subcat3.html
[4] => /category4.html/item4.html
[5] => /main_cat_slug5.html
[6] => /main_cat_slug6
[7] => /main_cat_slug7/sub_cat_slug7.html
[8] => /main_cat_slug8/item8.html
[9] => /main_cat_slug9/sub_cat_slug9/item9.html
)
[Main_Cat] => Array
(
[0] => category0.html
[1] =>
[2] => category2.html
[3] => category3.html
[4] => category4.html
[5] => main_cat_slug5.html
[6] => main_cat_slug6
[7] => main_cat_slug7
[8] => main_cat_slug8
[9] => main_cat_slug9
)
[Sub_Cat] => Array
(
[0] => subcat
[1] =>
[2] => subcat2.html
[3] => subcat3.html
[4] =>
[5] =>
[6] =>
[7] => sub_cat_slug7.html
[8] =>
[9] => sub_cat_slug9
)
[Item] => Array
(
[0] => item
[1] => item1
[2] => item2
[3] =>
[4] => item4
[5] =>
[6] =>
[7] =>
[8] => item8
[9] => item9
)
)
You can try this:
preg_match('~/(?<main_cat>[^/\s]++/?+)(?<sub_cat>[^/\s]++/?+)?'
. '(?>(?<filename>\S+?)\.html)?~', $url, $match);
print_r($match);
Note that you can access easily to the different parts with the named captures (useful to test if there is a subpattern or not.).

Categories