array_splice removing more than one item - php

I have the following method:
public function selectFinal(){
$db = new Database();
for($i = 0; $i < 5; $i++){
$key_id = mt_rand(0, count($this->candidates) - 1);
$itm = $this->candidates[$key_id];
$host = $itm["host"];
$item = $itm["item"];
$db->query("insert ignore into trends (trend_id, host, item) values (?, ?, ?)", array($this->nextId, $host, $item));
array_splice($this->candidates, $key_id, -1);
print_r($this->candidates);
$this->nextId++;
}
}
For the print_r() I am getting this output:
Array
(
[0] => Array
(
[host] => www.youtube.com
[item] => IytNBm8WA1c
)
[1] => Array
(
[host] => www.youtube.com
[item] => kffacxfA7G4
)
[2] => Array
(
[host] => www.youtube.com
[item] => kXYiU_JCYtU
)
[3] => Array
(
[host] => www.youtube.com
[item] => 7AVHXe-ol-s
)
[4] => Array
(
[host] => www.youtube.com
[item] => qkM6RJf15cg
)
)
Array
(
[0] => Array
(
[host] => www.youtube.com
[item] => IytNBm8WA1c
)
[1] => Array
(
[host] => www.youtube.com
[item] => qkM6RJf15cg
)
)
Array
(
[0] => Array
(
[host] => www.youtube.com
[item] => qkM6RJf15cg
)
)
Array
(
[0] => Array
(
[host] => www.youtube.com
[item] => qkM6RJf15cg
)
)
Array
(
[0] => Array
(
[host] => www.youtube.com
[item] => qkM6RJf15cg
)
)
The array will start with 5 or more items in it. What I would like to do is select a random item from the array and insert it into the database then remove it from the array. I want to do this 5 times to get 5 random items from the array. But for some reason it is selecting 1 then removing 3 items from the array, and I am not sure why (shown in the second section of code).
Edit: Final Working Result
public function selectFinal(){
$db = new Database();
for($i = 0; $i < 5; $i++){
$key_id = mt_rand(0, count($this->candidates) - 1);
$itm = array_values(array_merge([$this->nextId], array_splice($this->candidates, $key_id, 1)[0]));
$db->query("insert ignore into trends (trend_id, host, item) values (?, ?, ?)", $itm);
$this->nextId++;
}
}

You are more safe in splicing the element out and use that outtake. In case you made an error with that, you notice by not having correct values to store. This will make you more aware of a potential problem:
$key_id = mt_rand(0, count($this->candidates) - 1);
$itm = array_splice($this->candidates, $key_id, -1);
var_dump($itm);
See? You then can better pin-point the problem, e.g. -1 is not 1. See http://php.net/array_splice
public function selectFinal() {
$db = $this->db;
for ($i = 0; $i < 5; $i++)
{
$key_id = mt_rand(0, count($this->candidates) - 1);
$values = array_merge(
[$this->nextId], array_splice($this->candidates, $key_id, 1)
###
);
print_r($this->candidates);
$db->query(
"insert ignore into trends (trend_id, host, item) values (?, ?, ?)",
array_values($values)
);
$this->nextId++;
}
}

If you just want delete a array item of a specific key you can use -
unset($this->candidates[$key_id])

Related

PHP Create a Nested Array with indexes from a CSV file

I'm having a peculiar issue. I have a CSV file that has Comma Separated Values that I need to upload and then get Nested Array of values based on following 3 conditions;
The array will first loop through all values and get first 4 unique
characters. (Codes)
Match each column values with the with number of
columns in each row and give count of rows that matches 4 digit
codes. (Single_Devices for single column and Dual, Triple and Quad for respective columns count)
Match each column values with code and list all the
columns under the Devices. (Numbers)
CSV file
123429000000000
123429000000001
123429000000010,123429000000011
123429000000040,123429000000041
What I desire is;
Array
(
[Code] => 1234
(
[single_devices] => 2
(
[0] => Array
(
[0] => 123429000000000
)
[1] => Array
(
[0] => 123429000000001
)
)
[dual_devices] => 2
(
[0] => Array
(
[0] => 123429000000010
[1] => 123429000000011
)
[1] => Array
(
[0] => 123429000000040
[1] => 123429000000041
)
)
)
)
Is it possible?
I can manage JSON converted data or object or just associative nested array.
Edit: This is the code I wrote for which was only showing values and not indexes as I desired.
// Get all numbers in array
for ($j = 0; $j < count($csv_file[$i]); $j++){
$numbers[] = $csv_file[$i][$j];
}
// Get codes from numbers
for ($i = 0; $i < count($csv_file); $i++){
for ($j = 0; $j < count($csv_file[$i]); $j++){
$codes[] = substr($csv_file[$i][$j], 0, 4);
}
}
// Get unique codes from codes array
$codes = array_unique($codes);
// Get numbers and sort them codes and device count wise.
for ($i = 0; $i < count($csv_file); $i++){
for ($j = 0; $j < count($csv_file[$i]); $j++){
$q = count($csv_file[$i]); // set device count based on column count
if (count($csv_file[$i]) == $q){ // if device count is equal to column count
foreach ($codes as $code){ // loop through unique codes
if ($code == substr($csv_file[$i][$j], 0, 4)){ // if number's first 4 char matches code
// create array with code and then device count and add numbers
$devices[$code][$q.'_device_numbers'][$i][$j] = preg_replace('/\s+/', '', $csv_file[$i][$j]);
}
}
}
}
}
This is what I am getting from the above code.
Array
(
[1234] => Array
(
[1_sim_imeis] => Array
(
[0] => Array
(
[0] => 123429000000000
)
[1] => Array
(
[0] => 123429000000001
)
)
[2_sim_imeis] => Array
(
[2] => Array
(
[0] => 123429000000010
[1] => 123429000000011
)
[3] => Array
(
[0] => 123429000000040
[1] => 123429000000041
)
)
)
)
This is based on reading the file as a csv (using fgetcsv()) and extracting the first 4 digits of the first value on each line. It then uses another array to give the key for the 'single_devices' etc. key - using the count of the number of elements on the line (-1 as the array is 0 based)...
$fileName = "a.dat";
$output = [];
$baseData = [ 'single_devices', 'dual_devices', 'triple_devices', 'quad_devices' ];
$fh = fopen ( $fileName, "r" );
while ( ($data = fgetcsv($fh)) !== false ) {
$code = substr($data[0], 0, 4);
$output[$code][$baseData[count($data)-1]][] = $data;
}
fclose($fh);
print_r($output);
which with the test data gives...
Array
(
[1234] => Array
(
[single_devices] => Array
(
[0] => Array
(
[0] => 123429000000000
)
[1] => Array
(
[0] => 123429000000001
)
)
[dual_devices] => Array
(
[0] => Array
(
[0] => 123429000000010
[1] => 123429000000011
)
[1] => Array
(
[0] => 123429000000040
[1] => 123429000000041
)
)
)
With
while ( ($data = fgetcsv($fh)) !== false ) {
$code = substr($data[0], 0, 4);
if ( !isset($output[$code])) {
$output[$code] = ["code" => $code];
}
$deviceLabel = $baseData[count($data)-1];
$output[$code][$deviceLabel]['count'] =
($output[$code][$deviceLabel]['count'] ?? 0) + 1;
$output[$code][$deviceLabel][] = $data;
}
you can get an output of...
Array
(
[1234] => Array
(
[code] => 1234
[single_devices] => Array
(
[count] => 2
[0] => Array
(
[0] => 123429000000000
)
[1] => Array
(
[0] => 123429000000001
)
)

Sum array on key - possible or is the array not structured in a good way?

Have built the following array based on an accounting file and want to create sums from the [trans] subarray for all accounts based on the amount. Looked into array_column but have a feeling the array is not built correctly or in an efficient way for this? Any thoughts/suggestions much appreciated.
//Clarification
Hi! Many thanks. I was probably a bit unclear. For the total population of [trans] I want to sum the amount where the account is the same. So the array above would generate:
[1930] = -150.47-431.63
[5912] = 150.47
etc
[#VER] => Array
(
[A1] => Array
(
[verdatum] => 20150107
[vertext] => GOOGLE
[trans] => Array
(
[0] => Array
(
[account] => 1930
[amount] => -150.47
)
[1] => Array
(
[account] => 5912
[amount] => 150.47
)
[2] => Array
(
[account] => 2645
[amount] => 37.62
)
[3] => Array
(
[account] => 2614
[amount] => -37.62
)
)
)
[A2] => Array
(
[verdatum] => 20150118
[vertext] => Post
[trans] => Array
(
[0] => Array
(
[account] => 1930
[amount] => -431.63
)
[1] => Array
(
[account] => 5710
[amount] => 345.30
)
[2] => Array
(
[account] => 2641
[amount] => 86.33
)
)
)
)
Its simply a foreach loop to acheive your expected sum of amount
$temp = array();
$new = array();
foreach($arr as $key=>$value){
foreach($value["trans"] as $key2=>$value2){
if(in_array($value2["account"], $temp)){
$new[$value2["account"]] += $value2["amount"];
}else {
$new[$value2["account"]] = $value2["amount"];
$temp[] = $value2["account"];
}
}
}
print_r($new);
Live demo : https://eval.in/857342
Output will be
Array
(
[1930] => -582.1
[5912] => 150.47
[2645] => 37.62
[2614] => -37.62
[5710] => 345.3
[2641] => 86.33
)
$grand_total = 0;
array_walk($my_array['#VER'],function (&$ver) use (&$grand_total){
$ver['total_amount'] = 0;
foreach($ver['trans'] as $trans){
$ver['total_amount'] += $trans['amount'];
}
$grand_total += $ver['total_amount'];
});
So, simply loop through your "VER" then loop again on each trans. As simple as that. I've used both array_walk and foreach techniques, mainly to show you the two ways. You could prefer use two foreach, or two array_walk, it would work.
This script adds to a $grand_total variable, and also store the total of all transactions into each VER entry.
Modified:
$grand_total = 0;
array_walk($urarr['#VER'],function (&$ver) use (&$grand_total){
foreach($ver['trans'] as $trans){
if ($trans['amount'] < 0){
$neg += abs($trans['amount']);
}else{
$pos += abs($trans['amount']);
}
}
$diff = ($pos < $neg) ? "-".($neg - $pos) : ($pos - $neg);
$grand_total += $diff;
});
print $grand_total;

highcharts php array unset/reset keys after sorting

I have the following array:
Array
(
[0] => Array
(
[0] => 2015-07-18
[1] => 22 SSH
)
[1] => Array
(
[0] => 2015-07-18
[1] => 80 HTTP
)
[2] => Array
(
[0] => 2015-07-18
[1] => 3389 Remote Desktop
)
[3] => Array
(
[0] => 2015-07-19
[1] => 3389 Remote Desktop
)
[4] => Array
(
[0] => 2015-07-19
[1] => 3389 Remote Desktop
)
)
and the following function to bring the data in the needed format/array for highcharts:
$result = array();
$result[0] = array();
$result[0][data] = array();
foreach ($stack_stats_timeline as $key => &$value) {
if(!in_array($value[0], $result[0][data], true)) array_push($result[0][data], $value[0]);
$hash = $value[1];
$result[$hash][name] = $value[1];
$result[$hash][data][$value[0]] += 1;
}
so far so good... hoever the problem is that when i do
$result = json_encode($result);
print_r($result);
I get
[{"data":["2015-07-01","2015-07-02","2015-07-03"]},{"name":"8080 Unknown","data":{"2015-07-01":4,"2015-07-02":8,"2015-07-03":5}},{"name":"8118 Unknown","data":{"2015-07-01":3}},{"name":"3389 Remote Desktop","data":{"2015-07-01":14,"2015-07-02":52,"2015-07-03":65}},{"name":"80 HTTP","data":{"2015-07-01":3,"2015-07-02":12,"2015-07-03":7}},{"name":"8228 Unknown","data":{"2015-07-01":3}}]
the problem is in data when the format is:
{"key":number,"key":number}
this should be only:
{number,number}
QUESTION: How can I remove the array keys after I sorted the occurences by date?
I would probably do something along the lines of:
$headings = $result[0]['data'];
for ($i = 0; $i < count($result[1]); $i ++) {
$data = $result[1][$i]['data'];
$newdata = array();
foreach($headings as $key)
$newdata[] = isset($data[$key]) ? $data[$key] : 0;
$result[1][$i]['data'] = $newdata;
}

How to create a customized array from json file

i am trying to create a customized array out of my json file. But every time i run this, nothing comes out. Why is the happening??
This is my JSON:
[{"Account":null,"Addresses":[{"Address1":"Store Kongensgade 72","City":"K\u00d8BENHAVN K","CoAddress":null,"Country":{"AttributeBag":null,"Code":"DK","Text":"Danmark"},"Type":{"AttributeBag":null,"Code":"Postal","Text":"Postadress"},"ZipCode":"1264"}]
This is my code
$json = file_get_contents("somefile");
$decarr = json_decode($json, TRUE);
print_r($decarr);
This is my current output from my decarr array:
Array ( [0] => Array ( [Account] => [Addresses] => Array ( [0] => Array ( [Address1] => Store Kongensgade 72 [City] => KØBENHAVN K [CoAddress] => [Country] => Array ( [AttributeBag] => [Code] => DK [Text] => Danmark ) [Type] => Array ( [AttributeBag] => [Code] => Postal [Text] => Postadress ) [ZipCode] => 1264 ) ) .....there is much more, but i had to stripped down.
This is my code for how to create my own array.
$count = count($decarr);
$values = array();
$update_values = array();
for ($x=0; $x < $count; $x++)
{
$newrec = $decarr[$x];
$num = $newrec['Address1']; $num = mysql_real_escape_string($num);
$desc = $newrec['City']; $desc = mysql_real_escape_string($desc);
$freq = $newrec['ZipCode']; $freq = mysql_real_escape_string($freq);
$values[] = "('".$num."', '".$desc."', '".$freq."')";
}
print_r($values);
But this is what i am getting right now.
Array ( [0] => ('', '', '') [1] => ('', '', '')....and beyond
As you can see, the selected values won't store in my values array. why is the happening?
The Address1, City, and ZipCode properties are inside an object that is an item of the Addresses array.
Change
$newrec = $decarr[$x];
To:
$newrec = $decarr[$x]['Addresses'][0];
Or if you want, you could also add all addresses:
for ($y = 0; $y < count($decarr[$x]['Addresses']); $y++) {
$newrec = $decarr[$x]['Addresses'][$y];
...
$values[] = "('".$num."', '".$desc."', '".$freq."')";
}

Array driving me loop(y)

Pardon the pun in my title (heh) but this is seriously driving me nuts!
This is my code:
for ($i=0;$i < $a;$i++){
$total = (array)$orders -> Total -> Line[$i];
echo '<pre>';
print_r($total);
echo '</pre>';
}
...It outputs the following:
Array
(
[#attributes] => Array
(
[type] => Subtotal
[name] => Subtotal
)
[0] => 299.99
)
Array
(
[#attributes] => Array
(
[type] => Shipping
[name] => Shipping
)
[0] => 13.36
)
Array
(
[#attributes] => Array
(
[type] => Tax
[name] => Tax
)
[0] => 0.00
)
Array
(
[#attributes] => Array
(
[type] => GiftCertificate
[name] => Gift certificate discount (117943:#CAC7HXPXFUNNJ3MTGC:63.35 117372:#DK9T9TMTCTCTUWF9GC:250.00)
)
[0] => -313.35
)
Array
(
[#attributes] => Array
(
[type] => Total
[name] => Total
)
[0] => 0.00
)
My question is: how do I save each dollar amount [0] into a respective variable named according to the array['type']?
Rather than a variable (which could be done with variable variables), I recommend putting them into an array $prices, keyed by the type attributes.
$prices = array();
for ($i=0;$i < $a;$i++){
$total = (array)$orders -> Total -> Line[$i];
echo '<pre>';
print_r($total);
echo '</pre>';
// Append the price to an array using its type attribute as the
// new array key
$prices[$total['#attributes']['type']] = $total[0];
}
Untested, of course, but I believe it will do the job.
$var[] = array('type' => $total['#attributes']['type'], 'amount' => $total[0])
Something like this maybe?
$total_amount_by_type = array();
for ($i=0;$i < $a;$i++){
$total = (array)$orders -> Total -> Line[$i];
$total_amount_by_type[$total->type] = $total[0]
}
Are you looking for something like this:
for ($i=0;$i < $a;$i++){
$total = (array)$orders -> Total -> Line[$i];
// will create variables $Tax, $GiftCertificate etc
${$total['#attributes']['type']} = $total[0];
echo '<pre>';
print_r($total);
echo '</pre>';
}

Categories