I have an array of potentially 1000s of items that I need to feed to and API that can handle 10 at a time. So, can I do something like this?
$data = [ ... ];
$start = 0;
$step = 10;
foreach (api_function(array_slice($data, $start, $step))){
$start += $step;
}
Using Nigel Ren's answer the final code looks like this:
$results = BC_cust_query($qlist, true);
$start = 0;
$step = 10;
$stop = count($results);
while ($start < $stop){
print_r(array_slice($results, $start, $step));
$start += $step;
}
Where print_r() will be replace by the API call
You would need to keep repeating the call to the API for each slice, until there is no more data left (check the start against the length of the array). Assuming it returns blank, some thing like
$data = [ ... ];
$start = 0;
$step = 10;
$countData = count($data);
// Fetch block of data whilst some data to fetch.
while ($start < $countData &&
$dataBlock = api_function(array_slice($data, $start, $step))){
// Loop over this block
foreach ( $dataBlock as $dataItem) {
// Process item
}
// Move onto next block
$start += $step;
}
or use a for loop...
$data = [ ... ];
$step = 10;
$countData = count($data);
// Fetch block of data whilst some data to fetch.
for ($start = 0;$start < $countData; $start += $step) {
$dataBlock = api_function(array_slice($data, $start, $step));
// Loop over this block
foreach ( $dataBlock as $dataItem) {
// Process item
}
}
Related
I am trying to make a function to display client's items in an array, however only the first item id is shown in the array. What's wrong with my code? I guess I'm doing something wrong with the array.
Example of sItem value: https://pastebin.pl/view/e492ffa1
$items = array();
$client_item = bin2hex($u->sItem);
$x = 0;
for ($i = 0; $i < 78; $i++) {
$item = hexdec(reverse(substr($client_item, $x, 8)));
if ($item != 0) {
$ii = $db->get_object("SELECT * FROM Clients.dbo.ITEM WHERE Num =" . $item);
if (is_object($ii)) {
$items[] = array("ItemID" => $ii->Num, "ItemSlot" => $i);
}
}
$x += 16;
}
The code above will show just the first item in the array. All others are not shown.
var items = [{"ItemID":310511133,"ItemSlot":0}]
I am not sure what I'm doing wrong. If I remove $x += 16; then it will simply add more entries in the array with the first item id. I want more entries but not with the same item id obviously. :)
var items = [{"ItemID":310511133,"ItemSlot":0},{"ItemID":310511133,"ItemSlot":1},{"ItemID":310511133,"ItemSlot":2},{"ItemID":310511133,"ItemSlot":3},{"ItemID":310511133,"ItemSlot":4}....
This is the reverse function:
function reverse($str)
{
$len = strlen($str);
$i = $len - 2;
$ret = NULL;
while (0 <= $i) {
$ret .= substr($str, $i, 2);
$i -= 2;
}
return $ret;
}
Database Query not returning any object SELECT * FROM Clients.dbo.ITEM WHERE Num = $item
can you confirm values exists in database
you can echo $item value and see manually in database are those values exists.
I'm not sure if I did this right:
I have a total number of items, say 624. I would like to make a loop that sends 7 requests, the first 6 over 100 items each, the last over the remaining 24.
So I did some math to find out how many loops I have to go through.
// this is the total number of items
$total = $result['total_items'];
// if we split the total into such chunks
$chunksize = 50;
// we will get a rest of so many items
$rest = $total % $chunksize;
// so including the query for the rest, we will have to repeat the query so many times
$queries_no = (($total-$rest)/$chunksize)+1;
The above feels kinda clumsy. Is that the right way?
PS: After that, I can repeat the query the necessary times.
// prep loop
$i = 0;
$requested = 0;
$subscribers = [];
while ($i <= $queries_no){
// last item
if($i == $queries_no){
$chunksize = $rest;
}
$result = $this->monkeyApp->get('lists/'.$list_id.'/members?offset='.$requested.'&count='.$chunksize);
$subscribers = array_merge($subscribers,$result['members']);
$requested = $requested + $chunksize;
$i++;
}
$subscribers = [];
for ($count = $chunksize, $offset = 0; $offset < $total; $offset += $chunksize)
{
if ($offset + $chunksize > $total)
{
$count = $total % $chunksize;
}
$result = $this->monkeyApp->get("lists/$list_id/members?offset=$offset&count=$count");
$subscribers = array_merge($subscribers, $result['members']);
}
I am trying to make card game.
I have 6 variable that are stored in array. Than I use fisherYates method to randomize array, and display four of them.
Problem is, when I randomize it this way only, it will give only random output of those six, with all different types.
So I want that some repeats like, if you draw four cards, you get output of
ex: club, club, diamond,heart, or heart, star,star,heart.. if you get a point..
I thought to do it like this way: put the array in loop of 4 times, and every time it loops, it stores first, or last value in new array, so that way, I can have greater chances of combination of same cards in output array.
But I'm stuck, and I don't know how to do it :/
this is what I've tried so far
$diamond = 'cube.jpg';
$heart = 'heart.jpg';
$spade = 'spade.jpg';
$club = 'tref.jpg';
$star='star.jpg';
$qmark='qmark.jpg';
$time=microtime(35);
$arr=[$diamond,$heart,$spade,$club,$star,$qmark];
function fisherYatesShuffle(&$items, $time)
{
for ($i = count($items) - 1; $i > 0; $i--)
{
$j = #mt_rand(0, $i);
$tmp = $items[$i];
$items[$i] = $items[$j];
$items[$j] = $tmp;
}
return $items;
}
$i=0;
do {
$niz[$i]=fisherYatesShuffle($arr,$time);
reset($niz);
$i++;
} while ($i <= 3);
Got a solution. Was just to simply do foreach of first element of multidimensional array :)
Code goes like this:
$diamond = 'cube.jpg';
$heart = 'heart.jpg';
$spade = 'spade.jpg';
$club = 'tref.jpg';
$star='star.jpg';
$qmark='qmark.jpg';
$time=microtime(35);
$arr=[$diamond,$heart,$spade,$club,$star,$qmark];
$niz=array();
$i=0;
do {
$niz[$i]=fisherYatesShuffle($arr,$time);
//reset($niz);
$i++;
} while ($i <= 3);
foreach ($niz as $key ) {
$randomArr[]=$key[0]; ;
}
function fisherYatesShuffle(&$items, $time)
{
for ($i = count($items) - 1; $i > 0; $i--)
{
$j = #mt_rand(0, $i);
$tmp = $items[$i];
$items[$i] = $items[$j];
$items[$j] = $tmp;
}
return $items;
}
print_r($randomArr);
I've recently send my CV to one company that was hiring PHP developers. They send me back a task to solve, to mesure if I'm experienced enough.
The task goes like that:
You have an array with 10k unique elements, sorted descendant. Write function that generates this array and next write three different functions which inserts new element into array, in the way that after insert array still will be sorted descendant. Write some code to measure speed of those functions. You can't use PHP sorting functions.
So I've wrote function to generate array and four functions to insert new element to array.
/********** Generating array (because use of range() was to simple :)): *************/
function generateSortedArray($start = 300000, $elementsNum = 10000, $dev = 30){
$arr = array();
for($i = 1; $i <= $elementsNum; $i++){
$rand = mt_rand(1, $dev);
$start -= $rand;
$arr[] = $start;
}
return $arr;
}
/********************** Four insert functions: **************************/
// for loop, and array copying
function insert1(&$arr, $elem){
if(empty($arr)){
$arr[] = $elem;
return true;
}
$c = count($arr);
$lastIndex = $c - 1;
$tmp = array();
$inserted = false;
for($i = 0; $i < $c; $i++){
if(!$inserted && $arr[$i] <= $elem){
$tmp[] = $elem;
$inserted = true;
}
$tmp[] = $arr[$i];
if($lastIndex == $i && !$inserted) $tmp[] = $elem;
}
$arr = $tmp;
return true;
}
// new element inserted at the end of array
// and moved up until correct place
function insert2(&$arr, $elem){
$c = count($arr);
array_push($arr, $elem);
for($i = $c; $i > 0; $i--){
if($arr[$i - 1] >= $arr[$i]) break;
$tmp = $arr[$i - 1];
$arr[$i - 1] = $arr[$i];
$arr[$i] = $tmp;
}
return true;
}
// binary search for correct place + array_splice() to insert element
function insert3(&$arr, $elem){
$startIndex = 0;
$stopIndex = count($arr) - 1;
$middle = 0;
while($startIndex < $stopIndex){
$middle = ceil(($stopIndex + $startIndex) / 2);
if($elem > $arr[$middle]){
$stopIndex = $middle - 1;
}else if($elem <= $arr[$middle]){
$startIndex = $middle;
}
}
$offset = $elem >= $arr[$startIndex] ? $startIndex : $startIndex + 1;
array_splice($arr, $offset, 0, array($elem));
}
// for loop to find correct place + array_splice() to insert
function insert4(&$arr, $elem){
$c = count($arr);
$inserted = false;
for($i = 0; $i < $c; $i++){
if($elem >= $arr[$i]){
array_splice($arr, $i, 0, array($elem));
$inserted = true;
break;
}
}
if(!$inserted) $arr[] = $elem;
return true;
}
/*********************** Speed tests: *************************/
// check if array is sorted descending
function checkIfArrayCorrect($arr, $expectedCount = null){
$c = count($arr);
if(isset($expectedCount) && $c != $expectedCount) return false;
$correct = true;
for($i = 0; $i < $c - 1; $i++){
if(!isset($arr[$i + 1]) || $arr[$i] < $arr[$i + 1]){
$correct = false;
break;
}
}
return $correct;
}
// claculates microtimetime diff
function timeDiff($startTime){
$diff = microtime(true) - $startTime;
return $diff;
}
// prints formatted execution time info
function showTime($func, $time){
printf("Execution time of %s(): %01.7f s\n", $func, $time);
}
// generated elements num
$elementsNum = 10000;
// generate starting point
$start = 300000;
// generated elements random range 1 - $dev
$dev = 50;
echo "Generating array with descending order, $elementsNum elements, begining from $start\n";
$startTime = microtime(true);
$arr = generateSortedArray($start, $elementsNum, $dev);
showTime('generateSortedArray', timeDiff($startTime));
$step = 2;
echo "Generating second array using range range(), $elementsNum elements, begining from $start, step $step\n";
$startTime = microtime(true);
$arr2 = range($start, $start - $elementsNum * $step, $step);
showTime('range', timeDiff($startTime));
echo "Checking if array is correct\n";
$startTime = microtime(true);
$sorted = checkIfArrayCorrect($arr, $elementsNum);
showTime('checkIfArrayCorrect', timeDiff($startTime));
if(!$sorted) die("Array is not in descending order!\n");
echo "Array OK\n";
$toInsert = array();
// number of elements to insert from every range
$randElementNum = 20;
// some ranges of elements to insert near begining, middle and end of generated array
// start value => end value
$ranges = array(
300000 => 280000,
160000 => 140000,
30000 => 0,
);
foreach($ranges as $from => $to){
$values = array();
echo "Generating $randElementNum random elements from range [$from - $to] to insert\n";
while(count($values) < $randElementNum){
$values[mt_rand($from, $to)] = 1;
}
$toInsert = array_merge($toInsert, array_keys($values));
}
// some elements to insert on begining and end of array
array_push($toInsert, 310000);
array_push($toInsert, -1000);
echo "Generated elements: \n";
for($i = 0; $i < count($toInsert); $i++){
if($i > 0 && $i % 5 == 0) echo "\n";
printf("%8d, ", $toInsert[$i]);
if($i == count($toInsert) - 1) echo "\n";
}
// functions to test
$toTest = array('insert1' => null, 'insert2' => null, 'insert3' => null, 'insert4' => null);
foreach($toTest as $func => &$time){
echo "\n\n================== Testing speed of $func() ======================\n\n";
$tmpArr = $arr;
$startTime = microtime(true);
for($i = 0; $i < count($toInsert); $i++){
$func($tmpArr, $toInsert[$i]);
}
$time = timeDiff($startTime, 'checkIfArraySorted');
showTime($func, $time);
echo "Checking if after using $func() array is still correct: \n";
if(!checkIfArrayCorrect($tmpArr, count($arr) + count($toInsert))){
echo "Array INCORRECT!\n\n";
}else{
echo "Array OK!\n\n";
}
echo "Few elements from begining of array:\n";
print_r(array_slice($tmpArr, 0, 5));
echo "Few elements from end of array:\n";
print_r(array_slice($tmpArr, -5));
//echo "\n================== Finished testing $func() ======================\n\n";
}
echo "\n\n================== Functions time summary ======================\n\n";
print_r($toTest);
Results can be found here: http://ideone.com/1xQ3T
Unfortunately I was rated only 13 points out of 30 for this task (don't know how it was calculated or what exactly was taken in account). I can only assume that's because there are better ways to insert new element into sorted array in PHP. I'm searching this topic for some time now but couldn't find anything good. Maby you know of better approach or some articles about that topic?
Btw on my localhost (PHP 5.3.6-13ubuntu3.6 with Suhosin-Patch, AMD Athlon(tm) II X4 620) insert2() is fastest, but on ideone (PHP 5.2.11) insert3() is fastest.
Any ideas why? I suppose that array_splice() is tuned up somehow :).
//EDIT
Yesterday I thought about it again, and figured out the better way to do inserts. If you only need sorted structure and a way to iterate over it and your primary concern is the speed of insert operation, than the best choise would be using SplMaxHeap class. In SplMaxHeap class inserts are damn fast :) I've modified my script to show how fast inserts are. Code is here: http://ideone.com/vfX98 (ideone has php 5.2 so there won't be SplMaxHeap class)
On my localhost I get results like that:
================== Functions time summary ======================
insert1() => 0.5983521938
insert2() => 0.2605950832
insert3() => 0.3288729191
insert4() => 0.3288729191
SplMaxHeap::insert() => 0.0000801086
It may just be me, but maybe they were looking for readability and maintainability as well?
I mean, you're naming your variables $arr, and $c and $middle, without even bothering to place proper documentation.
Example:
/**
* generateSortedArray() Function to generate a descending sorted array
*
* #param int $start Beginning with this number
* #param int $elementsNum Number of elements in array
* #param int $dev Maximum difference between elements
* #return array Sorted descending array.
*/
function generateSortedArray($start = 300000, $elementsNum = 10000, $dev = 30) {
$arr = array(); #Variable definition
for ($i = 1; $i <= $elementsNum; $i++) {
$rand = mt_rand(1, $dev); #Generate a random number
$start -= $rand; #Substract from initial value
$arr[] = $start; #Push to array
}
return $arr;
}
I am trying to create a function which maps a recurring pattern of integers using an array.
As an example if I have a starting array of (0,1,3) and I know that I want to stop the pattern when I hit 15.
The pattern gets incremented by a fixed integer each time (lets say 4) so my final pattern should be..
0
1
3
4 (0 + 4)
5 (1 + 4)
7 (2 + 4)
8 (4 + 4)
9 (5 + 4)
11(7 + 4)
12(8 + 4)
13(9 + 4)
15(11+ 4)
Does anyone have any pointers on how this can be achieved?
My current implementation works but is stupidly inefficient which something like this...
$array = array(0,1,3);
$inc = 4;
$end = end($array);
$final = 15;
while($end < $final)
{
$tmp = array();
foreach($array AS $row)
{
$tmp = $row + $inc;
}
$array = merge($tmp, $array);
$end = end($array);
}
$array = array(0,1,3);
$inc = 4;
$final = 15;
$end = end($array);
while($end < $final)
{
$end += $inc;
$array[] = $end;
}
Or with a for loop:
$array = array(0,1,3);
$inc = 4;
$final = 15;
for($i = end($array) + $inc; $i <= $final; $i += $inc)
{
$array[] = $i;
}
Y'all are missing the fact that 4 is being added to the value in the array 2 keys back, not the last value.
This is the code you need (tested, and working)
$array = array(0,1,3);
$inc = 4;
$end = end($array);
$key = key($array);
$final = 15;
while ($end < $final) {
if ($array[$key-2] >= 0) {
$end = $array[$key-2] + $inc;
$array[] = $end;
$key++;
}
}
I also included in there a check to make sure the key being added to actually exists, though that may not be needed.
I assume that you want to have all the new values in the same array.
So:
//original array
$values = array(0, 1, 3);
//incremental value
$inc = 4;
//stop value
$stop = 15;
//set the index counter to the origin
$curr_index = 0;
//while the last value of the array is lower than the stop value
while($values[end($values)] < $stop)
{
//calculate the new value
$new_value = $values[$curr_index] + $inc;
//add the new value to the array
array_push($values, $new_value);
//update the index counter
$curr_index ++;
}
this code should work for any initial value in the array, any incremental value and any stop value.
<?php
function myArrayFunction(array $array, $inc = 4, $final = 15, $end = null)
{
if(!$end)
{
$end = end($array);
}
while($end < $final)
{
$end += $inc;
$array[] = $end;
}
return $array; //assume you're wanting $array back
}
This is minus any sort of testing or checking of injected values but you get the idea.
It would be better to know what you are trying to achieve here as the whole thing looks horribly overcomplicated, but...
$array = array(0,1,3);
$pattern = array();
$inc = 4;
$final = 15;
for ($base = 0; ; $base += $inc) {
foreach($array as $rem) {
if ($base + $rem > $final) break 2;
$pattern []= $base + $rem;
}
}
Alternatively,
$i = $v = 0;
while ($v < $final) {
$v = $pattern []= $pattern[$i++] + $inc;
}
(This assumes $final will be part of the pattern.)
If you can figure out how to calculate the number of elements will be in the array beforehand and assign that to $tum this should work.
<?php
$arr = array(0, 1, 3);
$inc = 4; // 6
$fin = 15; // 55
$num = count($arr);
$lum = 0;
$tum = 12; // 29
do
{
for($i = $lum; $i < $num; $i++)
{
$tar = $arr[$i] + $inc;
$arr[$tar] = $tar;
}
$lum = $num;
$num *= 2;
} while(end($arr) < $fin);
$arr = array_slice($arr, 0, $tum);
print_r($arr);
echo "\n";
?>