array_unique() not making the array unique - php

I am generating an array of numbers based on an equation then rounding to the nearest 100.
After that I want to get rid of duplicates, array_unique seemed like the natural choice for this situation, but is not working as intended.
I created a small sample to demonstrate this.
The PHP code is as follows:
var_dump($amounts);
array_unique($amounts);
var_dump($amounts);
The result of which is:
array(6) {
[0]=>
float(200)
[1]=>
float(300)
[2]=>
float(300)
[3]=>
float(400)
[4]=>
float(500)
[5]=>
float(500)
}
array(6) {
[0]=>
float(200)
[1]=>
float(300)
[2]=>
float(300)
[3]=>
float(400)
[4]=>
float(500)
[5]=>
float(500)
}
Can someone shed some light on what is happening here please?

array_unique does not modify the array by reference. You'll need to catch the returned value:
$amounts = array_unique($amounts);
Note: the keys of the returned array may no longer be contiguous. If you want to make them contiguous again then you should use array_values.
Example:
$amounts = array(100, 200, 200, 200, 300, 400);
var_dump($amounts);
array(6) {
[0]=>
int(100)
[1]=>
int(200)
[2]=>
int(200)
[3]=>
int(200)
[4]=>
int(300)
[5]=>
int(400)
}
// Make the array unique
$amounts = array_unique($amounts);
var_dump($amounts);
array(4) {
[0]=>
int(100)
[1]=>
int(200)
[4]=>
int(300) // Notice the gap, indexes 2 and 3 don't exist.
[5]=>
int(400)
}
// Make the keys contiguous
$amounts = array_values($amounts);
var_dump($amounts);
array(4) {
[0]=>
int(100)
[1]=>
int(200)
[2]=>
int(300)
[3]=>
int(400)
}

Related

How to Generate an Array of Random Number Sets in PHP?

I'm trying to figure out the best way to create an array of sets of randomly selected numbers from a range. So, for instance I have a range of numbers from which to select: 1-100. I want to generate X number of sets of 5 of those numbers WITHOUT DUPLICATES. So, I want to generate something like:
[3, 24, 32, 49, 68]
[2, 18, 43, 76, 98]
[10, 12, 23, 45, 67]
[5, 56, 64, 72, 90]
...
I know how to generate random numbers from a range once, I just am stuck on doing it X number of times without the possibility of duplicate sets.
One way to solve this problem is simply to generate the desired range $arr = range(1, 100), then shuffle it to randomize shuffle($arr) then chunk it to get sets of 5 $sets = array_chunk($arr, 5).
So the final answer:
$arr = range(1, 100); // gives us an array of 100 integers 1-100
shuffle($arr); // randomly orders those integers
$sets = array_chunk($arr, 5); // creats an array of arrays of sets of 5 integers
foreach ($sets as $set) {
echo implode(',', $set), "\n";
}
Gives you something like...
14,24,60,95,86
47,54,10,77,3
11,22,88,80,39
72,46,81,78,59
63,98,52,82,8
79,34,43,13,41
67,33,75,1,2
4,57,84,73,17
32,55,35,18,70
64,85,100,93,71
25,19,26,20,76
99,89,7,87,91
37,97,68,27,5
74,48,65,61,58
45,31,9,30,21
16,56,50,96,90
92,40,6,44,23
28,94,38,83,29
36,62,51,66,15
12,69,49,42,53
Alternative implementation
Another way to solve this problem, that doesn't require writing the entire array into memory at once and then resorting it randomly, would be to use a hashset that tracks all randomly generated integers to prevent duplicates. This gives us the same exact result except that we do both the random number generation and sorting in a single step instead of two. You can also even do the chunking in the same step this way.
Keep in mind, however, that this solution is technically slower since it's in unbounded time (we have to keep guessing if the number already exists).
I'm going to use a generator to implement this solution since it's easier to write than an Iterator pattern.
function randomizeIntegerXRangeChunked($start, $end, $chunks = 5): Generator
{
$inSet = []; // track the integers already in the set
for ($i = $start, $c = 0; $i <= $end; $i++) {
/* solution is in unbounded time */
while (isset($inSet[($n = mt_rand($start, $end))]));
$inSet[$n] = true;
yield $c => $n;
if (!($i % $chunks)) {
$c++;
}
}
}
$arr = [];
foreach (randomizeIntegerXRangeChunked(1, 100, 5) as $chunk => $int) {
$arr[$chunk][] = $int;
}
var_dump($arr);
The output will be similar to...
array(20) {
[0]=>
array(5) {
[0]=>
int(43)
[1]=>
int(52)
[2]=>
int(38)
[3]=>
int(73)
[4]=>
int(55)
}
[1]=>
array(5) {
[0]=>
int(59)
[1]=>
int(3)
[2]=>
int(71)
[3]=>
int(47)
[4]=>
int(50)
}
[2]=>
array(5) {
[0]=>
int(54)
[1]=>
int(19)
[2]=>
int(60)
[3]=>
int(40)
[4]=>
int(5)
}
[3]=>
array(5) {
[0]=>
int(26)
[1]=>
int(46)
[2]=>
int(93)
[3]=>
int(80)
[4]=>
int(63)
}
[4]=>
array(5) {
[0]=>
int(18)
[1]=>
int(45)
[2]=>
int(98)
[3]=>
int(1)
[4]=>
int(72)
}
[5]=>
array(5) {
[0]=>
int(37)
[1]=>
int(97)
[2]=>
int(15)
[3]=>
int(68)
[4]=>
int(8)
}
[6]=>
array(5) {
[0]=>
int(34)
[1]=>
int(14)
[2]=>
int(33)
[3]=>
int(24)
[4]=>
int(65)
}
[7]=>
array(5) {
[0]=>
int(4)
[1]=>
int(16)
[2]=>
int(13)
[3]=>
int(41)
[4]=>
int(86)
}
[8]=>
array(5) {
[0]=>
int(95)
[1]=>
int(12)
[2]=>
int(44)
[3]=>
int(66)
[4]=>
int(83)
}
[9]=>
array(5) {
[0]=>
int(67)
[1]=>
int(48)
[2]=>
int(91)
[3]=>
int(27)
[4]=>
int(79)
}
[10]=>
array(5) {
[0]=>
int(56)
[1]=>
int(25)
[2]=>
int(2)
[3]=>
int(64)
[4]=>
int(78)
}
[11]=>
array(5) {
[0]=>
int(57)
[1]=>
int(17)
[2]=>
int(74)
[3]=>
int(42)
[4]=>
int(69)
}
[12]=>
array(5) {
[0]=>
int(96)
[1]=>
int(20)
[2]=>
int(9)
[3]=>
int(28)
[4]=>
int(7)
}
[13]=>
array(5) {
[0]=>
int(30)
[1]=>
int(75)
[2]=>
int(21)
[3]=>
int(6)
[4]=>
int(89)
}
[14]=>
array(5) {
[0]=>
int(51)
[1]=>
int(36)
[2]=>
int(62)
[3]=>
int(58)
[4]=>
int(23)
}
[15]=>
array(5) {
[0]=>
int(85)
[1]=>
int(32)
[2]=>
int(100)
[3]=>
int(61)
[4]=>
int(49)
}
[16]=>
array(5) {
[0]=>
int(39)
[1]=>
int(87)
[2]=>
int(76)
[3]=>
int(70)
[4]=>
int(22)
}
[17]=>
array(5) {
[0]=>
int(88)
[1]=>
int(77)
[2]=>
int(10)
[3]=>
int(99)
[4]=>
int(53)
}
[18]=>
array(5) {
[0]=>
int(94)
[1]=>
int(35)
[2]=>
int(92)
[3]=>
int(90)
[4]=>
int(84)
}
[19]=>
array(5) {
[0]=>
int(81)
[1]=>
int(82)
[2]=>
int(31)
[3]=>
int(29)
[4]=>
int(11)
}
}
You can try it like this as well.
// Array
$NumberArray = array();
$TempArray = array(); // Used for storing randoms while we check via if statement.
// Loop 5 times.
for ($x=0; $x<=4; $x++) {
// Random Number 1-100
$RandomNumber = rand(1,100);
// We can use Array Push to add to the array and check using in_array.
array_push($TempArray, $RandomNumber);
// Check first thing in temp array and see if its already in number array. (If not then push)
if (!in_array(reset($TempArray), $NumberArray)) {
array_push($NumberArray, reset($TempArray)); // Add to NumberArray
// Clear Temp Array
$TempArray = array();
} else {
// Add to the loop
$x--;
}
}
print_r($NumberArray);
This outputs an array like such:
Array
(
[0] => 32
[1] => 26
[2] => 59
[3] => 96
[4] => 34
)

How do I check a json object for the existence of a key with php server side?

Ok, So I am working with the reddit api using the php sdk wrapper by #jcleblanc ( https://github.com/jcleblanc/reddit-php-sdk )
That information is not necessarily relevant to the question but I want to give you a frame of reference so you understand what I am looking to do.
The api returns what I believe is a mixed json object as a response when I make calls to reddit. The response length varies and is not consistent. The only this that is consistent is if the action was successful, it returns the key pair
["success"]=> bool(true)
I want to basically search whatever is returned by the api for the key "success" and I can simply evaluate for true or false. Can anybody help with some code to do that?
Here is a sample complete return:
object(stdClass)#1171 (2) { ["jquery"]=> array(29) { [0]=> array(4) { [0]=> int(0) [1]=> int(1) [2]=> string(4) "call" [3]=> array(1) { [0]=> string(4) "body" } } [1]=> array(4) { [0]=> int(1) [1]=> int(2) [2]=> string(4) "attr" [3]=> string(4) "find" } [2]=> array(4) { [0]=> int(2) [1]=> int(3) [2]=> string(4) "call" [3]=> array(1) { [0]=> string(7) ".status" } } [3]=> array(4) { [0]=> int(3) [1]=> int(4) [2]=> string(4) "attr" [3]=> string(4) "hide" } [4]=> array(4) { [0]=> int(4) [1]=> int(5) [2]=> string(4) "call" [3]=> array(0) { } } [5]=> array(4) { [0]=> int(5) [1]=> int(6) [2]=> string(4) "attr" [3]=> string(4) "html" } [6]=> array(4) { [0]=> int(6) [1]=> int(7) [2]=> string(4) "call" [3]=> array(1) { [0]=> string(0) "" } } [7]=> array(4) { [0]=> int(7) [1]=> int(8) [2]=> string(4) "attr" [3]=> string(3) "end" } [8]=> array(4) { [0]=> int(8) [1]=> int(9) [2]=> string(4) "call" [3]=> array(0) { } } [9]=> array(4) { [0]=> int(1) [1]=> int(10) [2]=> string(4) "attr" [3]=> string(8) "redirect" } [10]=> array(4) { [0]=> int(10) [1]=> int(11) [2]=> string(4) "call" [3]=> array(1) { [0]=> string(66) "https://www.reddit.com/r/mysubreddit/comments/12hyas2/my_no_link_post/" } } [11]=> array(4) { [0]=> int(1) [1]=> int(12) [2]=> string(4) "attr" [3]=> string(4) "find" } [12]=> array(4) { [0]=> int(12) [1]=> int(13) [2]=> string(4) "call" [3]=> array(1) { [0]=> string(11) "*[name=url]" } } [13]=> array(4) { [0]=> int(13) [1]=> int(14) [2]=> string(4) "attr" [3]=> string(3) "val" } [14]=> array(4) { [0]=> int(14) [1]=> int(15) [2]=> string(4) "call" [3]=> array(1) { [0]=> string(0) "" } } [15]=> array(4) { [0]=> int(15) [1]=> int(16) [2]=> string(4) "attr" [3]=> string(3) "end" } [16]=> array(4) { [0]=> int(16) [1]=> int(17) [2]=> string(4) "call" [3]=> array(0) { } } [17]=> array(4) { [0]=> int(1) [1]=> int(18) [2]=> string(4) "attr" [3]=> string(4) "find" } [18]=> array(4) { [0]=> int(18) [1]=> int(19) [2]=> string(4) "call" [3]=> array(1) { [0]=> string(12) "*[name=text]" } } [19]=> array(4) { [0]=> int(19) [1]=> int(20) [2]=> string(4) "attr" [3]=> string(3) "val" } [20]=> array(4) { [0]=> int(20) [1]=> int(21) [2]=> string(4) "call" [3]=> array(1) { [0]=> string(0) "" } } [21]=> array(4) { [0]=> int(21) [1]=> int(22) [2]=> string(4) "attr" [3]=> string(3) "end" } [22]=> array(4) { [0]=> int(22) [1]=> int(23) [2]=> string(4) "call" [3]=> array(0) { } } [23]=> array(4) { [0]=> int(1) [1]=> int(24) [2]=> string(4) "attr" [3]=> string(4) "find" } [24]=> array(4) { [0]=> int(24) [1]=> int(25) [2]=> string(4) "call" [3]=> array(1) { [0]=> string(13) "*[name=title]" } } [25]=> array(4) { [0]=> int(25) [1]=> int(26) [2]=> string(4) "attr" [3]=> string(3) "val" } [26]=> array(4) { [0]=> int(26) [1]=> int(27) [2]=> string(4) "call" [3]=> array(1) { [0]=> string(1) " " } } [27]=> array(4) { [0]=> int(27) [1]=> int(28) [2]=> string(4) "attr" [3]=> string(3) "end" } [28]=> array(4) { [0]=> int(28) [1]=> int(29) [2]=> string(4) "call" [3]=> array(0) { } } } ["success"]=> bool(true) }
The code you gave mean you were calling json_decode($response). This return an object.
It should be:
$resArray = json_decode($response, true)
Which return an associated array.
Then to use:
if (isset($resArray['success'])) {
//your logic here
}
Your object has two properties: jquery and success.
All you need to get the success property is this:
$success = $your_object->success;
As long as the returned object has a success property, that's all you should need to do, regardless of how many other properties it has, or the size of any of its other properties.
If you aren't sure if the object will have the success property, you can use
$success = !empty($your_object->success);
which will evaluate to true if the property exists and is true, and false otherwise.
You might be able to just throw it into
json_decode
If it complains about the format you can do some direct string manipulation beforehand and then you'll be able to reference it directly as an associative array.
Use var_dump to get familiar with the structure after you get a successful parse.

Sorting an array before inserting to database

I hate to beat a dead horse, but here goes. I have an Apache2 server running and I create my own php/html forms for in and output with mysql. Works great, I love it.
My problem is I have a huge array that I want to insert to MySQL but it needs to be sorted first (0<00). I've gone through the many Q & A covering the subject here and the code supplied works on a single array just fine. However, I need to loop through about 7000 sets and I'd like the output to be in original format but I have had no luck making that work as desired.
$data = array(
array(29,11,15,30,33),
array(30,11,25,18,02),
array(12,15,08,06,18),
array(17,20,03,21,02),
array(26,27,12,30,11),
array(05,25,34,11,16),
array(29,11,06,30,14),
array(05,26,12,18,33),
array(23,28,05,22,09),
array(05,36,31,32,27),
array(02,06,03,05,14)
);
An easy way to sort each sub array:
$data = array(
array(29,11,15,30,33),
array(30,11,25,18,02),
array(12,15,08,06,18),
array(17,20,03,21,02),
array(26,27,12,30,11),
array(05,25,34,11,16),
array(29,11,06,30,14),
array(05,26,12,18,33),
array(23,28,05,22,09),
array(05,36,31,32,27),
array(02,06,03,05,14)
);
foreach($data as &$value){ // Mind the & byref value
sort($value);
}
var_dump($data);
// $data is now sorted over here
The output:
array(11) {
[0]=>
array(5) {
[0]=>
int(11)
[1]=>
int(15)
[2]=>
int(29)
[3]=>
int(30)
[4]=>
int(33)
}
[1]=>
array(5) {
[0]=>
int(2)
[1]=>
int(11)
[2]=>
int(18)
[3]=>
int(25)
[4]=>
int(30)
}
[2]=>
array(5) {
[0]=>
int(0)
[1]=>
int(6)
[2]=>
int(12)
[3]=>
int(15)
[4]=>
int(18)
}
[3]=>
array(5) {
[0]=>
int(2)
[1]=>
int(3)
[2]=>
int(17)
[3]=>
int(20)
[4]=>
int(21)
}
[4]=>
array(5) {
[0]=>
int(11)
[1]=>
int(12)
[2]=>
int(26)
[3]=>
int(27)
[4]=>
int(30)
}
[5]=>
array(5) {
[0]=>
int(5)
[1]=>
int(11)
[2]=>
int(16)
[3]=>
int(25)
[4]=>
int(34)
}
[6]=>
array(5) {
[0]=>
int(6)
[1]=>
int(11)
[2]=>
int(14)
[3]=>
int(29)
[4]=>
int(30)
}
[7]=>
array(5) {
[0]=>
int(5)
[1]=>
int(12)
[2]=>
int(18)
[3]=>
int(26)
[4]=>
int(33)
}
[8]=>
array(5) {
[0]=>
int(0)
[1]=>
int(5)
[2]=>
int(22)
[3]=>
int(23)
[4]=>
int(28)
}
[9]=>
array(5) {
[0]=>
int(5)
[1]=>
int(27)
[2]=>
int(31)
[3]=>
int(32)
[4]=>
int(36)
}
[10]=>
&array(5) {
[0]=>
int(2)
[1]=>
int(3)
[2]=>
int(5)
[3]=>
int(6)
[4]=>
int(14)
}
}
EDIT
Or like #JREAM suggest, you can use array_walk:
array_walk($data, sort);

How do I sort a multidimensional array in php by 2 values

I have been playing with the array_multisort function but I am struggling to get it to work with the array that I have.
Here is a var dump of the multi dimensional array I am trying to sort:
array(2) {
[1]=> array(6) {
["totalprice"]=> float(103.32)
["itemsprice"]=> float(83.33)
["deliveryprice"]=> float(19.99)
["qualityscore"]=> int(100)
["reliabilityscore"]=> int(100)
["itemtemplates"]=> array(4) {
[1]=> array(3) {
["price"]=> float(374)
["qty"]=> int(200)
["name"]=> string(17) "English A2 Poster"
}
[3]=> array(3) {
["price"]=> float(374)
["qty"]=> int(500)
["name"]=> NULL
}
[6]=> array(3) {
["price"]=> float(83.333333333333)
["qty"]=> int(100)
["name"]=> string(16) "French A3 Poster"
}
[5]=> array(3) {
["price"]=> float(83.333333333333)
["qty"]=> int(5000) ["name"]=> NULL
}
}
}
[2]=> array(6) {
["totalprice"]=> float(103.32)
["itemsprice"]=> float(83.33)
["deliveryprice"]=> float(19.99)
["qualityscore"]=> int(80)
["reliabilityscore"]=> int(100)
["itemtemplates"]=> array(4) {
[1]=> array(3) {
["price"]=> float(374)
["qty"]=> int(200)
["name"]=> string(17) "English A2 Poster"
}
[3]=> array(3) {
["price"]=> float(374)
["qty"]=> int(500)
["name"]=> NULL
}
[6]=> array(3) {
["price"]=> float(83.333333333333)
["qty"]=> int(100)
["name"]=> string(16) "French A3 Poster"
}
[5]=> array(3) {
["price"]=> float(83.333333333333)
["qty"]=> int(5000) ["name"]=> NULL
}
}
}
[3]=> array(6) {
["totalprice"]=> float(83.32)
["itemsprice"]=> float(63.33)
["deliveryprice"]=> float(19.99)
["qualityscore"]=> int(60)
["reliabilityscore"]=> int(40)
["itemtemplates"]=> array(4) {
[1]=> array(3) {
["price"]=> float(374)
["qty"]=> int(200)
["name"]=> string(17) "English A2 Poster"
}
[3]=> array(3) {
["price"]=> float(374)
["qty"]=> int(500)
["name"]=> NULL
}
[6]=> array(3) {
["price"]=> float(83.333333333333)
["qty"]=> int(100)
["name"]=> string(16) "French A3 Poster"
}
[5]=> array(3) {
["price"]=> float(83.333333333333)
["qty"]=> int(5000) ["name"]=> NULL
}
}
}
}
I need to sort by the total price ASC and then by the quality score DESC.
I've tried the following:
$sorted = array_multisort($array['totalprice'], SORT_ASC, SORT_NUMERIC,
$array['qualityscore'], SORT_NUMERIC, SORT_DESC);
Unfortunately that doesn't work. Is anyone a bit more savvy with this function and may know where i'm going wrong? or if there is a simple alternative to this function?
Thanks in Advance!
Use the usort() function.
You'll obviously need to write your own sort function for it. Pass that function into usort() to sort by whatever criteria you need.
See the manual page linked above for how to define your sort function.
Try following code:
$totalprices = array();
$qualityscores = array();
foreach ($array as $value) {
$totalprices[] = $value['totalprice'];
$qualityscores[] = $value['qualityscore'];
}
array_multisort($totalprices, SORT_ASC, $qualityscores, SORT_DESC, $array);
RTM http://php.net/manual/en/function.array-multisort.php :)

Fixing multidimensional array

I'm trying to make a multidimensional array that should print out like this (without formatting):
array(3) {
[0]=> array(5) {
[0]=> int(0)
[1]=> string(5) "Arena"
[2]=> string(18) "2012-05-3017:00:00"
[3]=> string(18) "2012-05-3000:00:00"
[4]=> string(33) "Masquerade Checkin (Participants)"
},
[1]=> array(5) {
[0]=> int(0)
[1]=> string(10) "Workshop 1"
[2]=> string(18) "2012-05-3017:00:00"
[3]=> string(18) "2012-05-3000:00:00"
[4]=> string(15) "Death Note (Live)"
},
[2]=> array(5) {
[0]=> int(0)
[1]=> string(7) "Video 6"
[2]=> string(18) "2012-05-3017:00:00"
[3]=> string(18) "2012-05-3000:00:00"
[4]=> string(26) "Takeuchi Fan Panel"
}
}
Notice from the above code that the inner array() length is always 5.
Here is my code below:
$loopsArray = array();
$data=array();
// graphing info come in here.
foreach ($events as $key => $event) {
$el=$event['event_location'] ;
$eln=$event['event_locationName'];
$ed=$event['event_date'];
$es=$event['event_start'];
$ee=$event['event_end'];
$en=$event['event_name'];
array_push($loopsArray,$el,$eln, $ed.$es,$ed.$ee,$en);
array_push($data,$loopsArray);
}
var_dump($data);
Here the print out
array(27) {
[0]=> array(5) {
[0]=> int(0)
[1]=> string(5) "Arena"
[2]=> string(18) "2012-05-3017:00:00"
[3]=> string(18) "2012-05-3000:00:00"
[4]=> string(33) "Masquerade Checkin (Participants)"
}
[1]=> array(10) {
[0]=> int(0)
[1]=> string(5) "Arena"
[2]=> string(18) "2012-05-3017:00:00"
[3]=> string(18) "2012-05-3000:00:00"
[4]=> string(33) "Masquerade Checkin (Participants)"
[5]=> int(13)
[6]=> string(11) "Autograph 1"
[7]=> string(18) "2012-06-2419:00:00"
[8]=> string(18) "2012-06-2422:00:00"
[9]=> string(17) "Parents and Anime"
}
//... continues
}
Notice that the inner arrays length double each iteration. array(5) array(10) array(15)array(20).
It doubles up to 60 elements in the last inner array. Each inner array should only have 5 elements in them. I don't understand why it is doubling or how to fix it.
Can you look over my loop and let me know how to fix it?
I have to use this multidimensional array for this code to work in JpGraph.
TIP : write $loopsArray = array(); inside foreach
better approach
instead of
array_push($loopsArray,$el,$eln, $ed.$es,$ed.$ee,$en);
array_push($data,$loopsArray);
try this
$temp = array ($el,$eln, $ed.$es,$ed.$ee,$en);
$data[] = $temp;

Categories