I have an array that is like this:
Array{
10 - 2011 Headlight Assembly Nissan Versa
11 - LH 07-11 INS QTLY O.E.M - FREE SAME DAY SHIPPING
12 - 000
13 - A0
14 - 40626A1
15 - $165 actual
16 - More Desc Stuff
}
that is produced from a simple dom result. There are multiple items within the list. What I would like to do is reset the key back to 10 after 17 is reached so that I can loop over all the results within the array and find the proper values without having to look for say keys 10, 14, 15 - and then keys 20, 24, 25, etc.
Not quite sure if I have explained it correctly, or how to accomplish it. Any guidance is appreciated. Thanks in advance!
Well, for the indexes to deny I suggest you tu use an array of these indexes. and to loop through this array from 10 to 16 and then come back to 10, I suggest you to do this
$indexes_to_deny = [14,15,16];
$index = 10;
while( condition to stop the loop )
{
if($index%17===0)
$index = 10;
if(in_array($index,$indexes_to_deny))
{
$index++;
continue;
}
/*
your code here
you can access the items inside the array with $array[$index]
*/
$index++:
}
My solution was to use array_slice to drop off the unnecessary items and then array_chuck the rest and finally just drop the rest at a break point.
Related
I have a following array (php):
[
[id=>1,weight=]
[id=>2,weight=]
[id=>3,weight=]
[id=>4,weight=]
]
I need to create all possible versions of this array asigning 0-100 weight to each item['weight'] with a step of N.
I don't know how this type of problems are called. It is NOT permutation/combination.
Lets say N is 10, I am aiming to get:
[
[
[id=>1,weight=10]
[id=>2,weight=10]
[id=>3,weight=10]
[id=>4,weight=70]
]
[
[id=>1,weight=10]
[id=>2,weight=10]
[id=>3,weight=20]
[id=>4,weight=60]
]
[
[id=>1,weight=10]
[id=>2,weight=10]
[id=>3,weight=30]
[id=>4,weight=50]
]
[
[id=>1,weight=10]
[id=>2,weight=10]
[id=>3,weight=40]
[id=>4,weight=40]
]
...all possible combination of weights for id=x.
[
[id=>1,weight=70]
[id=>2,weight=10]
[id=>3,weight=10]
[id=>4,weight=10]
]
]
Sum of 4 item['weights'] in array on same level is always 100 (or 0.1). And inside parent array I've all possible combinations of weights from 10-100 for id=x.
This problem is sometimes described as allocating identical balls into distinct bins. You didn't specify your problem exactly, so I'll take a guess here but the logic will be identical.
I'll assume you're distributing b = N/step balls into 4 bins.
Think of the balls all in a row, and then using 3 bars to separate the balls into 4 bins:
*|||*****.
If N=10 and you're distributing 100 points, the above example is the same is 30, 20, 0, 50. If zeroes aren't allowed, you can reduce the amount you're distributing by 4*b and assume each bin starts out with N/step in it (so you're distributing the leftover points).
The number of ways to do this is choose(balls + bins - 1, bins - 1).
Theres probably a better way, but heres my attempt:
$result=array(); // Empty array for your result
$array=range(1117,7777); // Make an array with every number between 1117 and 7777
foreach ($array as $k=>$v) { // Loop through numbers
if ((preg_match('/[890]/',$v) === 0) && (array_sum(str_split($v, 1)) === 10)) {
// If number does not contain 8,9 or 0 and sum of all 4 numbers is 10
// Apply function to multiply each number by 10 and add to result array
$result[] = array_map("magnitude", str_split($v, 1));
}
}
function magnitude($val) { // function to multiply by 10 for array map
return($val * 10);
}
print_r($result);
Working demo here
EDIT
Sorry I realised my code explanation isn't totally clear and I condensed it all a bit too much to make it easy to follow.
In your example the first array would contain (10,10,10,70). For the sake of simplicity I divided everything by 10 for the calculations and then just multiplied by 10 once I had a result, so your array of (10,10,10,70) becomes (1,1,1,7). Then your final array would be (70,10,10,10) which would become (7,1,1,1).
My approach was to first to create an array containing every combination of these four numbers, which I did in two steps.
This line $array=range(1117,7777); creates an array like this (1117, 1118, 1119 ... 7775, 7776, 7777) (My number range should really have been 1117 - 7111 instead of 1117-7777).
Applying str_split($v, 1) to each value in the loop splits each 4 digit number in the array into another array conatining 4 single digit numbers, so 1117 will become (1, 1, 1, 7) etc
As each of your items can't have a weight below 10 or above 70 we use (preg_match('/[890]/',$v) === 0) to skip any arrays which have 0,8 or 9 in them anywhere, then array_sum(str_split($v, 1)) === 10) adds up the four digits in the array and only returns arrays which total 10 (you wanted ones which total 100, but I divided by 10 earlier).
array_map applies a function to each element in an array. In my example the function multiplies each value by 10, to undo the fact I divided by 10 earlier.
When you say is it possible to alter steps, can you give me a couple of examples of other values and the output you want for them?
If you want a totally different approach and using mysql isn't a problem then this also works:
Create a new table with a single row. Insert all the values you need to check
INSERT INTO `numbers` (`number`) VALUES
(10),
(20),
(30),
(40),
(50),
(60),
(70);
Then your php looks like this
$result=array();
try {
$dbh = new PDO('mysql:host=aaaaa;dbname=bbb', 'ccc', 'dddd');
foreach($dbh->query('SELECT *
FROM numbers a
CROSS JOIN // A cross join returns the cartesian product of rows
numbers b // so every row with every combination of the other rows
CROSS JOIN
numbers c
CROSS JOIN
numbers d
ON
a.number = b.number OR a.number != b.number') as $row) {
if (($row[0] + $row[1] + $row[2] + $row[3]) === 100) {
$result[] = $row;
}
}
$dbh = null;
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
print_r($result);
I am building a leaderboard (scorebored) for a poker tournament. My aim is to echo data to a table to display scores for the season and scores all time. I want the table to run in order with the highest season points at the top.
I am getting an error message that reads:
Notice: Undefined index: season in C:\wamp\www\UPT Site\leaders.php on line 11
When I print_r an array from the $allplayers array, it shows that all the players arrays are going in correctly, including the [season] key and value declared on line 6 in the bit below...
Can anyone please tell me how to fix my code? (note, the real code doesn't have line numbers in it, I just added them here to make discussion easier).
1 foreach($allplayers as $player){
2 $i = $player[1];
3 if (${"seasonplayerid" . $i}){
4 $sum = array_sum(${"seasonplayerid" . $i});}
5 //$sum = points this season.
6 ${"playerid" . $i}['season'] = $sum;
7 }
8 function val_sort($array,$key) {
9 //Loop through and get the values of our specified key
10 foreach($array as $k=>$v) {
11 $b[] = strtolower($v[$key]);
12 }
13 asort($b);
14 /* foreach($b as $k=>$v) {
15 $c[] = $array[$k];
16 }return $c;
17 */
18 }
19 $sorted = val_sort($allplayers, '[season]');
20 foreach($allplayers as $player){
21 $i = $player[1];
22 echo ("<tr><td>" . $player[0] . $t . ${"playerid" . $i}[3] . $t . ${"playerid" . $i}[4] . $t. ${"playerid" . $i}['season'] . $t. count(${"seasonplayerid" . $i}). "</td><tr>");
23 }
Here is the print_r output for array $playerid1:
Array ( [0] => Jonathan Thompson [1] => 1 [2] => 2015-S 3 [3] => 944 [4] => 7 [season] => 470 )
Here is a key of the information in the array:
/*
$allplayers is a multidimentional array, containing many arrays of players called $playerid1, $playerid2, $playerid3 etc
playerid1[0] = Player name
playerid1[1] = Player ID
playerid1[2] = Current season
playerid1[3] = total points earned
playerid1[4] = total games played games
playerid1[season] = points earned in current season
*/
Looks like at line 19 you are trying to pass key in second parameter but defined it incorrectly.So, to call function val_sort($array,$key) you have to do something like that.
Therefore at line 19 change
$sorted = val_sort($allplayers, '[season]');
to
$sorted = val_sort($allplayers, 'season');
Also i suggest you to use data table it is good and fast
Instead of below line
$sorted = val_sort($allplayers, '[season]');
you should pass the key as below
$sorted = val_sort($allplayers, 'season');
Hope this helps.
I did a dodgy quick fix in this instance.
I wrote a loop to array_pop each array inside the main array, and created a new variable for each piece of data as the array_pop loop was going.
I also array_pushed the data I wanted to sort by and an ID number to a new array.
I used rsort to sort the new array, then looped through it using the ID number to reconstruct a 3rd array in the order I wanted to output data.
Next time I will take the advice of #rocky and do a data table. I may even go back to redo this page as a data table. To be honest, I'd never heard of a data table before yesterday. Once I've given this project over to the boss I'll be investing my time in learning about data tables and AJAX.
Thank you all for your tips, but the quick fix will have to do this time as I am time poor (This site needs to be live tomorrow morning).
Say I have a list of 65 strings.
I need to split this single list into multiple "pools" that have a similar amount of strings.
The amount cannot be over 32.
In this list of 65, they're all ranked from 1st to 65th.
For a list of 65 strings, it'd split into one pool of 21, and two pools of 22.
For a list of 34 strings, it'd split into one pool of 18, and one pool of 18.
For a list of 115 strings, it'd split into one pool of 28, and three pools of 29.
And so on.
However, the new lists need to be fairly ranked.
In example it should be like so:
rank 1 in pool 1
rank 2 in pool 2
rank 3 in pool 3
rank 4 in pool 1
rank 5 in pool 2
rank 6 in pool 3
This way, rank 1 and rank 4, become rank 1 and 2 in their new list.
Same goes for the rest.
I'm thinking I'd need to use array_chunk in combination with a modulo operation, but I can't seem to wrap my head around it.
This is not as difficult as it might seem:
// settings
$cellCount = 115;
$maxPoolSize = 32;
// create test array with numbered strings
$testArray = array_fill(1,$cellCount,'Cell ');
foreach ($testArray as $key => $value) $testArray[$key] .= $key;
// determine the number of pools needed
$arraySize = count($testArray);
$poolCount = ceil($arraySize/$maxPoolSize);
// fill the pools
$poolNo = 0;
foreach ($testArray as $cell)
{
$poolArray[$poolNo][] = $cell;
$poolNo++;
if ($poolNo == $poolCount) $poolNo = 0;
}
// show result
echo '<pre>';
print_r($poolArray);
echo '</pre>';
I'm sure there are other solutions, but this seems to do the job.
I think you're on the right way, by using array_chunk and a modulo operation, that's the way i would choose.
It would be like:
$countarray = count($myarray);
$modulo = 2;
while ($countarray>32)
{
$result = $countarray/$modulo;
if($result>32)
$modulo++;
}
$newpool = array_chunk($myarray, $modulo);
I'm not a god in php, so i hope it will help ! Sorry for my poor english.
I merged two arrays together that both contained a string(url) and int(score). the following is a sample of the outome. Whenever a string is duplicated, i need to remove that string and its corresponding int. For example, on the 4th line (www.thebeatles.com/ - 30) should be removed. The 5th and 6th lines should also be removed as they appear already with a different score.
http://www.thebeatles.com/ - 55
http://en.wikipedia.org/wiki/The_Beatles - 49
http://www.beatlesstory.com/ - 45
http://www.thebeatles.com/ - 30
http://en.wikipedia.org/wiki/The_Beatles - 28
http://www.beatlesstory.com/ - 26
http://www.beatlesagain.com/ - 24
http://www.thebeatlesrockband.com/ - 23
http://www.last.fm/music/The+Beatles - 22
http://itunes.apple.com/us/artist/the-beatles/id136975 - 20
http://www.youtube.com/watch?v=U6tV11acSRk - 18
http://blekko.com/ws/http://www.thebeatles.com/+/seo - 17
http://www.adriandenning.co.uk/beatles.html - 16
http://www.npr.org/artists/15229570/the-beatles - 15
http://mp3.com/artist/The%2BBeatles - 14
http://www.beatles.com/ - 13
http://www.youtube.com/watch?v=TU7JjJJZi1Q - 12
http://www.guardian.co.uk/music/thebeatles - 11
http://www.cirquedusoleil.com/en/shows/love/default.aspx - 9
http://www.recordingthebeatles.com/ - 7
http://www.beatlesbible.com/ - 5
I'm new to PHP and my best efforts to get array_unique() to work have failed. Really appreciate some help guys!
Here is a function that merges two arrays and discards any duplications, hopes it helps:
function merge_links($arr_l, $arr_r) {
$new_links = array();
$links = array_merge($arr_l, $arr_r); //the big list with every links
foreach($links as $link) {
$found = false; //did we found a duplicate?
//check if we already have it
foreach($new_links as $new_link) {
if($new_link['url'] == $link['url']) {
//duplicate
$found = true;
break;
}
}
//not found, so insert it
if(!$found) {
$new_links[] = $link;
}
}
return $new_links;
}
$arr1[0]['url'] = 'http://test.nl';
$arr1[0]['score'] = 30;
$arr1[1]['url'] = 'http://www.google.nl';
$arr1[1]['score'] = 30;
$arr2[0]['url'] = 'http://www.tres.nl';
$arr2[0]['score'] = 30;
$arr2[1]['url'] = 'http://test.nl';
$arr2[1]['score'] = 30;
print_r(merge_links($arr1, $arr2));
You can make link as key of the array which contains link and score. Corresponding to key there will always be one value. But the one which is added in the last will be there in your final array.
Well, even technically, those strings are not unique. i.e. They are completely different.
http://www.thebeatles.com/ - 55
http://www.thebeatles.com/ - 30
So, array_unique() will not give you the required output. One way of solving this issue is by defining a separate array and storing the URI and the number separately. A manageable form would be this.
array(
array("http://www.thebeatles.com", 55),
array("http://www.thebeatles.com", 30)
);
I want to construct an array of 3 offers that output in a random order. I have the following code and whilst it does output 3 random offers it doesn't appear to be random. The first value in the generated array always seems to be from the 1st 2 records in my offers table. The offers table only has 5 records in it (I dont know if this is affecting things).
$arrayOfferCount = $offerCount-1;
$displayThisManyOffers = 3;
$range = range(0, $arrayOfferCount);
$vals = array_rand($range, $displayThisManyOffers);`
Any help or advice would be appreciated.
Working fine here. Benchmark it over lots of runs instead of just gut feeling... here it is for 1,000 tries:
<?php
$offerCount = 5;
$arrayOfferCount = $offerCount-1;
$displayThisManyOffers = 3;
$range = range(0, $arrayOfferCount);
for($i = 0; $i < 1000; $i++) {
$vals = array_rand($range, $displayThisManyOffers);
foreach($vals as $val) {
$counts[$val]++;
}
}
sort($counts);
print_r($counts);
Generates:
Array
(
[0] => 583
[1] => 591
[2] => 591
[3] => 610
[4] => 625
)
I know that mt_rand() is much better PRNG.
However, in your case you need to let the database select them for you
SELECT * FROM ads ORDER BY RAND() LIMIT 0, 3
It is probably randomly picking which to display, but displaying them in the same order they appear in your array. If you do it enough times (~20) you should get the third one to show up once if this is the case (chances of choosing exactly the last 3 out of 5 would be 1 in 5*4, so around every 20th one you'll see the third option appear).
array_rand seems not to work properly sometimes (see PHP-Manual comments).
Workaround: Get the array size and pick a random index using the function mt_rand