How to navigate through an array of unordered keys - php

Hello i want to pagination an array with for loop but the problem is my array keys is not like(1,2,3,4,5 ... etc) ,,
for ($x=0; $x<$members_per_page; $x++) {
$position = (int) ($currentPage-1) * $members_per_page + $x;
$member = get_userdata($members[$position]);
blackfyre_clan_members_links($member,$post_meta_arr, $post_id, $isleader);
if ( $position >= $last_key ) break;
}
and my array content is :
Array
(
[4] => Array
(
[boid] => 4
[cr_nickname] =>
)
[564] => Array
(
[boid] => 564
[cr_nickname] =>
)
) .... ETC

You could force your array to have sequential keys by using array_values like below:
for ($x=0; $x<$members_per_page; $x++) {
$position = (int) ($currentPage-1) * $members_per_page + $x;
$member = get_userdata(array_values($members)[$position]);
blackfyre_clan_members_links($member,$post_meta_arr, $post_id, $isleader);
if ( $position >= $last_key ) break;
}
However a (possibly) better way to paginate would be :
$offset = (int) ($currentPage-1) * $members_per_page;
$slice = array_slice ($members, $offset, $members_per_page,true);
array_walk($slice, function ($member) use ($post_meta, $post_id, $isleader) {
blackfyre_clan_members_links($member,$post_meta_arr, $post_id, $isleader);
});

Just use foreach ($members as $member){} instead of for

Related

create block by block array from foreach loop

Hi I am trying to print multiple array with selected block e.x. 2/3
But I am not getting exact result. I need some help.
Here is my program
<?php
$process_block = 2;// this is the block
$args = array(
0=> 16083,
1=> 16090);
$user_id_start = $args[0];
$user_id_end = $args[1];
$end_page = ($user_id_end - $user_id_start)/$process_block ;
if ($end_page > floor($end_page)){
$end_page = floor($end_page)+1;
}
for($i=1; $i<=$end_page; $i++){
if($i==$end_page){
$id_from = ($user_id_start + ($i-1) * $process_block + 1);
$id_to = $user_id_end;
}elseif($i==1){
$id_from = $user_id_start;
$id_to = $user_id_start + $i * $process_block;
}else{
$id_from = ($user_id_start + ($i-1) * $process_block + 1);
$id_to = $user_id_start + $i * $process_block;
}
$param['id_from'] = isset($id_from) ? $id_from : '';
$param['id_to'] = isset($id_to) ? $id_to : '';
print_r($param);
}
?>
And the output it is producing:
Array
(
[id_from] => 16083
[id_to] => 16085
)
Array
(
[id_from] => 16086
[id_to] => 16087
)
Array
(
[id_from] => 16088
[id_to] => 16089
)
Array
(
[id_from] => 16090
[id_to] => 16090
)
My expected array should like this may be. with 2 difference between numbers
Array
(
[id_from] => 16083
[id_to] => 16085
)
Array
(
[id_from] => 16086
[id_to] => 16088
)
Array
(
[id_from] => 16089
[id_to] => 16090
)
Fiddle
I thought I'd whip this up in a jiffy. But this was maybe version... 4? I feel like there should be a simpler solution, but I sure didn't find it. It should handle changes in the size of your range too.
<?php
$process_block = 3;// this is the block
$args = array(
0=> 16083,
1=> 16090);
$user_id_start = $args[0];
$user_id_end = $args[1];
$diff = $user_id_end - $user_id_start;
$pages = ceil(($user_id_end - $user_id_start) / $process_block);
for($i=0; $i<=$pages; $i++){
if (($user_id_start+$i*$process_block)>$user_id_end)break;
echo $i.'--'.($user_id_start+$i*$process_block).':::';
$param['id_from'] = $i*$process_block+$user_id_start;
$page_end = ($i+1) * $process_block+$user_id_start-1;
$param['id_to'] = $page_end>$user_id_end ? $user_id_end : $page_end;
print_r($param);
}
?>

Splitting a Associative Array Based off if Condition of Value

I'm combining an array based off a MySQL Query:
$newskus = array();
$newqtys = array();
$sql1 = $db->query("//QUERY//");
while($row = $sql1->fetch_assoc()) {
$newskus[] = $row['SKU'];
$newqtys[] = $row['Quantity'];
}
$newskusandqtys = array_combine($newskus, $newqtys);
This gives me an associative array like so:
Array
(
[Product 1] => -1
[Product 2] => 0
[Product 3] => 3
)
I'm looking to split this array based off the condition of the integer value.
That is, if the value is above 0, it'll put the contents into a variable $newqtysabovezero
Ending with an expected output of
Array
(
[Product 3] => 3
)
And the other way around, if the value is greater than or equal to 0, put this into an array variable $newqtysbelowzero with an expected output of
Array
(
[Product 1] => -1
[Product 2] => 0
)
I'm able to do this with a numerical array, but it of course is not passing the key:
foreach( $newqtys as $item ) {
if ( $item > '0' ) {
$newqtysabovezero[] = $item;
} elseif ( $item <= '0') {
$newqtysbelowzero[] = $item;
}
}
How would I modify this to get my expected output?
Here is one way:
foreach( $newqtys as $key => $item ) {
if ( $item > '0' ) {
$newqtysabovezero[$key] = $item;
} elseif ( $item <= '0') {
$newqtysbelowzero[$key] = $item;
}
}
And here is a method using array_filter():
$in = array(
'Product 1' => -1,
'Product 2' => 0,
'Product 3' => 3
);
function at_and_below($v) {
return $v <= 0;
}
function above($v) {
return $v > 0;
}
$newqtysabovezero = array_filter($in, 'above');
$newqtysbelowzero = array_filter($in, 'at_and_below');
At first, to get all values from the 'Quantity' field as integers you should cast them to integer type:
...
while($row = $sql1->fetch_assoc()) {
$newskus[] = $row['SKU'];
$newqtys[] = (int) $row['Quantity'];
}
$newskusandqtys = array_combine($newskus, $newqtys);
Then, you can easily separate values which are greater than OR equal/less than 0:
foreach (newskusandqtys as $k => $item) {
if ($item > 0) {
$newqtysabovezero[$k] = $item;
} else {
$newqtysbelowzero[$k] = $item;
}
}
You can skip the array_combine part, and just read the values into the final arrays as you fetch them.
while($row = $sql1->fetch_assoc()) {
if ($row['Quantity'] > 0) {
$newqtysabovezero[$row['SKU']] = $row['Quantity'];
} else {
$newqtysbelowzero[$row['SKU']] = $row['Quantity'];
}
}

Search a multidimensional array for duplicates and return duplicate values and array key

I have the following multidimensional array:
$ancestors = array(
[1] =>array("Andrew","Adele"),
[2] =>array("Bertha","Bill","Billy","Blake"),
[3] =>array("Cathy","Case","Cory","Creek","Andrew","Ceaser","Cece","Childer"));
I am trying to search the rows and return duplicate values along with the array key of the lowest number the duplicate appears and return values to an associative array:
$common = array("Andrew"=>"1");
// merge all array in one
$new = array();
foreach($ancestors as $i)
$new = array_merge($new, $i);
// make array value => count and sort in in descendant order
$ar = array_count_values($new);
arsort($ar);
// save result array while count > 1
$result = array();
foreach($ar as $k => $v) {
if ($v < 2) break;
$result[$k] = array_search($k, $new) + 1;
}
print_r($result);
We have to compare each row with following rows, so row 1 with 2 and 3, row 2 with 3, row 3 with nothing (it is already compared).
To do this, we use a base-1 for to loop through all $ancestors elements except last, then we compare each name with greater ancestors:
$result = array();
/* Loop count($ancestors) -1: */
for( $i = 1; $i<count( $ancestors ); $i++ )
{
/* Loop for each name: */
foreach( current( $ancestors ) as $val )
{
/* If name is already in result, skip: */
if( isset( $result[$val] ) ) continue;
/* Loop for each following ancestors: */
foreach( array_slice( $ancestors, $i, Null, True ) as $key => $row )
{
if( in_array( $val, $row ) ) $result[ $val ] = key( $ancestors );
}
}
next( $ancestors );
}
For this $ancestors:
$ancestors = array(
1 =>array( "Andrew","Adele" ),
2 =>array( "Bertha","Bill","Billy","Blake","Adele" ),
3 =>array( "Cathy","Case","Cory","Creek","Andrew","Ceaser","Bill","Cece","Childer" ),
4 =>array( "Cathy" )
);
the result is:
Array
(
[Andrew] => 1
[Adele] => 1
[Bill] => 2
[Cathy] => 3
)
First combine all the names into one array, with names as keys and arrays of generation indexes as values:
foreach ($ancestors as $generation_key => $generation) {
foreach ($generation as $name) {
$combined[$name][] = $generation_key;
}
}
Then limit the combined results to values having more than one instance of the name:
$duplicates = array_filter($combined, function($x) { return count($x) > 1; });
Then convert the arrays to single values using min:
foreach ($duplicates as &$value) {
$value = min($value);
}
unset($value);

Sorting Array by an added variable

Adding a variable to the end of a mysql query.
Now I need to be able to sort by the associated value. Can someone help? I have tried several different sorting methods.
$result2 = mysqli_query($datacon,
"SELECT * FROM spreadsheet
WHERE brand = '$brand'
AND package = '$package'
AND HIDE_FROM_SEARCH = '0'
GROUP BY ACCTNAME $pages->limit");
echo mysqli_error($datacon);
while($row = mysqli_fetch_array($result2)) {
$lat_B=$row['LATITUDE'];
$long_B=$row['LONGITUDE'];
$lat_A = round($lat_A,2);
$long_A = round($long_A,2);
$lat_B = round($lat_B,2);
$long_B = round($long_B,2);
$distance = new calcDist($lat_A, $long_A, $lat_B, $long_B);
$distance = $distance->calcDist($lat_A, $long_A, $lat_B, $long_B);
$distance = round($distance,2);
$locationSort=array($row);
$locationSort['distance']=$distance;
FOR EACH SOMETHING?
}
I have amended my previous post to reflect my usage of an answer.
$result2 = mysqli_query($datacon,"SELECT * FROM spreadsheet WHERE brand = '$brand'
AND package = '$package' and HIDE_FROM_SEARCH = '0' GROUP BY ACCTNAME $pages->limit");
echo(mysqli_error($datacon));
class sortBydistance
{
function sortBydistance($a, $b) {
if ($a['distance'] == $b['distance']) {
return 0;
}
return ($a['distance'] < $b['distance']) ? -1 : 1;
}
}
while($row = mysqli_fetch_array($result2))
{
$lat_B=$row['LATITUDE'];
$long_B=$row['LONGITUDE'];
$lat_A = round($lat_A,2);
$long_A = round($long_A,2);
$lat_B = round($lat_B,2);
$long_B = round($long_B,2);
$distance = new calcDist($lat_A, $long_A, $lat_B, $long_B);
$distance = $distance->calcDist($lat_A, $long_A, $lat_B, $long_B);
$distance = round($distance,2);
}
$locationSort=array($row);
$locationSort['distance']=$distance;
uasort($locationSort, array($this, "sortBydistance"));
print_r($locationSort);
Probably you are not retrieving correctly the $bran and $package variables..
$result2 = mysqli_query($datacon,
"SELECT * FROM spreadsheet
WHERE brand = '".$brand."'
AND package = '".$package."'
AND HIDE_FROM_SEARCH = '0'
GROUP BY ACCTNAME ".$pages->limit.");
First, create your array of entries, and store it in an array, we will call $rows.
You want to use the PHP function usort here to provide a custom sorting callback.
Let's say you have an array like the following:
$rows = array(
array("latitude" => 5, "distance" => 10),
array("latitude" => 10, "distance" => 5),
array("latitude" => 56, "distance" => 48)
);
You expect this array of $rows to be reordered so that the entry with latitude == 10 is first, latitude == 5 is second, and latitude == 56 is third, based on their distance.
usort($rows, function ($a, $b) {
$a = $a['distance'];
$b = $b['distance'];
return $a == $b ? 0 : $a > $b ? 1 : -1;
});
Output
Array
(
[0] => Array
(
[latitude] => 10
[distance] => 5
)
[1] => Array
(
[latitude] => 5
[distance] => 10
)
[2] => Array
(
[latitude] => 56
[distance] => 48
)
)
See this demonstration at ideone.com
Alternatively, you could try to find a SortedArray implementation that would keep the elements sorted as they were inserted to the array, rather than only when you call usort() on the array. That's a little too advanced for this question, though.
Try this after your while loop:
uasort($locationSort, 'sortBydistance');
// or uasort($locationSort, array($this, "sortBydistance")); if you are using withing a class
print_r($locationSort);
function sortBydistance($a, $b) {
if ($a['distance'] == $b['distance']) {
return 0;
}
return ($a['distance'] < $b['distance']) ? -1 : 1;
}

most efficient method of turning multiple 1D arrays into columns of a 2D array

As I was writing a for loop earlier today, I thought that there must be a neater way of doing this... so I figured I'd ask. I looked briefly for a duplicate question but didn't see anything obvious.
The Problem:
Given N arrays of length M, turn them into a M-row by N-column 2D array
Example:
$id = [1,5,2,8,6]
$name = [a,b,c,d,e]
$result = [[1,a],
[5,b],
[2,c],
[8,d],
[6,e]]
My Solution:
Pretty straight forward and probably not optimal, but it does work:
<?php
// $row is returned from a DB query
// $row['<var>'] is a comma separated string of values
$categories = array();
$ids = explode(",", $row['ids']);
$names = explode(",", $row['names']);
$titles = explode(",", $row['titles']);
for($i = 0; $i < count($ids); $i++) {
$categories[] = array("id" => $ids[$i],
"name" => $names[$i],
"title" => $titles[$i]);
}
?>
note: I didn't put the name => value bit in the spec, but it'd be awesome if there was some way to keep that as well.
Maybe this? Not sure if it's more efficient but it's definitely cleaner.
/*
Using the below data:
$row['ids'] = '1,2,3';
$row['names'] = 'a,b,c';
$row['titles'] = 'title1,title2,title3';
*/
$categories = array_map(NULL,
explode(',', $row['ids']),
explode(',', $row['names']),
explode(',', $row['titles'])
);
// If you must retain keys then use instead:
$withKeys = array();
foreach ($row as $k => $v) {
$v = explode(',', $v);
foreach ($v as $k2 => $v2) {
$withKeys[$k2][$k] = $v[$k2];
}
}
print_r($categories);
print_r($withKeys);
/*
$categories:
array
0 =>
array
0 => int 1
1 => string 'a' (length=1)
2 => string 'title1' (length=6)
...
$withKeys:
array
0 =>
array
'ids' => int 1
'names' => string 'a' (length=1)
'titles' => string 'title1' (length=6)
...
*/
Just did a quick simple benchmark for the 4 results on this page and got the following:
// Using the following data set:
$row = array(
'ids' => '1,2,3,4,5',
'names' => 'abc,def,ghi,jkl,mno',
'titles' => 'pqrs,tuvw,xyzA,BCDE,FGHI'
);
/*
For 10,000 iterations,
Merge, for:
0.52803611755371
Merge, func:
0.94854116439819
Merge, array_map:
0.30260396003723
Merge, foreach:
0.40261697769165
*/
Yup, array_combine()
$result = array_combine( $id, $name );
EDIT
Here's how I'd handle your data transformation
function convertRow( $row )
{
$length = null;
$keys = array();
foreach ( $row as $key => $value )
{
$row[$key] = explode( ',', $value );
if ( !is_null( $length ) && $length != count( $row[$key] ) )
{
throw new Exception( 'Lengths don not match' );
}
$length = count( $row[$key] );
// Cheap way to produce a singular - might break on some words
$keys[$key] = preg_replace( "/s$/", '', $key );
}
$output = array();
for ( $i = 0; $i < $length; $i++ )
{
foreach ( $keys as $key => $singular )
{
$output[$i][$singular] = $row[$key][$i];
}
}
return $output;
}
And a test
$row = convertRow( $row );
echo '<pre>';
print_r( $row );

Categories