Create PHP Array Where Matching Keys have Some Value - php

This is the first post from a PHP noob. My question relates to an HTML/PHP form which posts the following three types of data generated by a MySQL query:
ID (always posted via a hidden input field)
Mileage (only some entries may be completed, others might be left blank)
Vehicle Type (always posted via a hidden input field)
This data is all for one of three companies that are selected on the page preceding the data-posting page ie.
Step One: Choose company and year. Press submit.
Step Two: See results from MySQL query and enter in mileages where necessary. Press submit.
Step Three: (that's why I'm here)
I've stuffed this data into what I (probably mistakenly) believe is a multidimensional array called $idmilearray by using the following code:
if(isset($_POST['mileage'])) {
$mileagenumber = $_POST['mileage'];
}
if(isset($_POST['idnos'])) {
$idnumber = $_POST['idnos'];
}
if(isset($_POST['vehicle'])) {
$vehicletype = $_POST['vehicle'];
}
$idmilearray = array(
'ids' => $idnumber,
'mileage' => $mileagenumber,
'vtype' => $vehicletype
);
foreach($idmilearray as $inputs) {
$inputs = $idmilearray['ids'];
$inputs = $idmilearray['mileage'];
$inputs = $idmilearray['vtype'];
}
If I execute a print_r on the $idmilearray I get the following results:
Array
(
[ids] => Array
(
[0] => 35
[1] => 22
[2] => 32
[3] => 38
[4] => 36
[5] => 39
[6] => 16
[7] => 20
[8] => 48
[9] => 46
)
[mileage] => Array
(
[0] => 334
[1] => 56
[2] =>
[3] => 43
[4] =>
[5] =>
[6] =>
[7] =>
[8] => 11
[9] => 5
)
[vtype] => Array
(
[0] => 10T
[1] => 10T
[2] => 10T
[3] => Artic
[4] => 10T
[5] => Artic
[6] => Artic
[7] => 10T
[8] => Artic
[9] => 10T
)
What I would like to do is to create another array (the values of which I can use in later SQL queries) but only where the keys contain something in [ids][0], [mileage][0] and [vtype][0] and so on and so forth. I'd like to use [mileage] as the 'reference array'.
I've been playing around with array_intersect_key and array_diff_key but I've hit a big and rather a nasty wall. Can anyone help or give some pointers?
Thanks very much for your time.
Regards,
External.

You can use what you have to insert directly into mysql as follows:
foreach ( $idmilearray['mileage'] as $KEY => $VAL ) {
if ( empty($VAL) ) continue;
$query = "INSERT INTO `tableName` (id, mileage, vtype) VALUES ('{$idmilearray['ids'][$KEY]}', '$VAL', '{$idmilearray['vtype'][$KEY]}')";
}
Or if you really want to merge everything for further processing or whatever reason you can do it like so:
$NewArray = [];
foreach ( $idmilearray['mileage'] as $KEY => $VAL ) {
if ( empty($VAL) ) continue;
$NewArray[] = array('id' => $idmilearray['ids'][$KEY], 'mileage' => $VAL, 'vtype' => $idmilearray['vtype'][$KEY]);
}
Ofcourse there are many other possible ways to do this, but these are the easiest given what you currently have.

Just add another foreach, inside your existing foreach and fill your new array by checking the old array values with if (!empty($old_array)) {}
Example:
foreach($idmilearray as $inputs) {
$inputs = $idmilearray['ids'];
$inputs = $idmilearray['mileage']; // This is the one you want, right?
$inputs = $idmilearray['vtype'];
}
To do the job you need, it would be something like this:
$new_array = []; // Short array syntax (PHP 5.3+)
foreach($idmilearray as $inputs) {
$inputs = $idmilearray['ids'];
foreach($idmilearray['mileage'] as $mileage) {
if (!empty($mileage)) {
$new_array[] = $mileage;
}
}
$inputs = $idmilearray['vtype'];
}
Now you have new array ($new_array) filled only with the keys that links to existing values.
I hope it helps you.

Related

Change default numeric associative array keys to "number" only without affecting array values

I have a form at http://97.74.37.64/ (visit it first) . It has only one textarea where visitor can fill upto 15000 number of mobile numbers. after submit it should be converted into an array (This one I have done).
Now, this array is like this below..
Array ( [0] => 9810000000 [1] => 9810000001 [2] => 9810000002 [3] => 9810000003 [4] => 9810000004 [5] => 9810000005 [6] => 9810000006 [7] => 9810000007
and so on..
Now, I want to change the key of the array to string "number" so it should be like
Array ( [number] => 9810000000 [number] => 9810000001 [number] => 9810000002 [number] => 9810000003 [number] => 9810000004 [number] => 9810000005 [number] => 9810000006 [number] => 9810000007
I want to do the above mentioned thing. Because I want to insert the mobile numbers into the MySQL table (one mobile number each row). This is the multiple insertion in MySQL table. My table name is srchlist with 2 fields id(its auto_increment & we don't need to mention or insert it) and number for which I am making array keys as number. So finally it should be inserted like below
id | number
---------------
1 9810000000
2 9810000001
3 9810000002
and so on entire array values should be inserted..
What about just organizing these values into an array of arrays? That way you can bulk insert them into your table or insert them as part of a loop if need be:
array(
array("number" => 1), array("number" => 2), array("number" => 3)
)
You can do something like this:
Controller:
// Array ( [0] => 9810000000 [1] => 9810000001 [2] => 9810000002 [3] => 9810000003 [4] => 9810000004 [5] => 9810000005 [6] => 9810000006 [7] => 9810000007)
$number = array('9810000000','9810000001','9810000002','9810000003',,'9810000004','9810000005','9810000006','9810000007');
foreach($number as $row)
{
$number1[]['number'] = $row;
}
$this->M_admin->numbers($number1); //call modal function
Modal:
function numbers($number)
{
// insert into db as batch
$this->db->insert_batch('numbers', $number);
}

PDO fetchAll() primary key as array group key

I want to store the contents of a specific database into an array, grouped by their primary keys. (Instead of the useless way PDO fetchAll() organises them).
My current code:
$DownloadsPDO = $database->dbh->prepare("SELECT * FROM `downloads`");
$DownloadsArray = $DownloadsPDO->execute();
$DownloadsArray = $DownloadsPDO->fetchAll();
Which then outputs:
Array ( [0] => Array ( [id] => 0 [0] => 0 [path] => /xx-xx/testfile.zip [1] => /xx-xx/testfile.zip [name] => Test Script [2] => Test Script [status] => 1 [3] => 1 ) [1] => Array ( [id] => 1 [0] => 1 [path] => /xx-xx/test--file.zip [1] => /xxxx/testfile.zip [name] => New Script-UPDATE [2] => New Script-UPDATE [status] => 1 [3] => 1 ) )
I was considering to use PDO::FETCH_PAIR, however I will be very soon expanding the amount of data I want to be able to use on this script. This works currently, but when I start to expand the amount of downloads and more clients come into play, obviously the way the data is grouped causes an issue.
Is it possible for me to group each array by their primary key (which is id)?
You can just use
$results = array_map('reset', $stmt->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC))
PDO::FETCH_GROUP|PDO::FETCH_ASSOC returns an array of arrays. The first column is used as the key, and then within key is an array of all the results for that key. However, in our scenario each key will only contain 1 row. reset() returns the first element in array, thus eliminating 1 level of nesting.
This should yield what you are looking for :
$results = $pdos->fetchAll(\PDO::FETCH_UNIQUE|\PDO::FETCH_ASSOC);
I decided to just loop through the results with fetch() and enter them into an array as I go along, this is the code I have used and it works just fine:
$DownloadsPDO = $database->dbh->query("SELECT * FROM `downloads`");
$Array = array();
while ($d = $DownloadsPDO->fetch()) {
$Array[$d['id']]["id"] = $d['id'];
$Array[$d['id']]["name"] = $d['name'];
$Array[$d['id']]["path"] = $d['path'];
}
// Outputs
Array ( [1] => Array ( [id] => 1 [name] => Test Script [path] => /xxxx/testfile.zip ) [2] => Array ( [id] => 2 [name] => New Script-UPDATE [path] => /xxxx/testfile.zip ) )
Which uses the primary key (being id) as the name for the array key, and then adds the data into it.
Thought I would add this as the answer as this solved it, thanks to the guys that helped out and I hope this is helpful to anyone else hoping to achieve the same thing.
I'd like to point out the only solution that works for me:
fetchAll(\PDO::FETCH_GROUP|\PDO::FETCH_UNIQUE|\PDO::FETCH_ASSOC);
Beware that this will strip the first column from the resultset. So the query must be:
SELECT id_keyname AS arrkey, id_keyname, .... FROM ...
I'm still suggesting you to loop using fetch() method. Otherwise, you can use array_reduce() to iterate over the array. A sample on codepad is here.
The code(in human readable form) will be:
$myFinalArray = array_reduce($myInputArray, function($returnArray, $temp) {
$temp2 = $temp['id'];
unset($temp['id']);
$returnArray[$temp2] = $temp;
return $returnArray;
}
);
So, my question is; is it possible for me to group each array by their
primary key (which is id)
Off course, you have 2 options here: Either to change the query or parse a result-set.
So, I'm sure you don't want to change query itself, so I'd go with parsing result-set.
Note:
You should use prepared SQL statements when they make sense. If you want to bind some parameters then its OKAY. But in this case, you only want get get result-set, so prepare() and fetch() will be kinda overdo.
So, you have:
Array ( [0] => Array ( [id] => 0 [0] => 0 [path] => /xx-xx/testfile.zip [1] => /xx-xx/testfile.zip [name] => Test Script [2] => Test Script [status] => 1 [3] => 1 ) [1] => Array ( [id] => 1 [0] => 1 [path] => /xx-xx/test--file.zip [1] => /xxxx/testfile.zip [name] => New Script-UPDATE [2] => New Script-UPDATE [status] => 1 [3] => 1 ) )
And you want:
Array( [id] => Array('bar' => 'foo') ....)
Well, you can do something like this:
$stmt = $database->dbh->query("SELECT * FROM `downloads`");
$result = array();
foreach($stmt as $array){
$result[$array['id']] = $array;
}
print_r($result); // Outputs: Array(Array('id' => Array(...)))

Compare two multi-multi-dimensionals-arrays

I got the following array (shortened ... multiple dot mean that they are data there, both array start at entry 1 until the end.
Array
(
[12U_S_136_15_29_141] => Array
(
.....
[35] => Array
(
[stop_sequence] => 35
[stop_id] => 1601394
)
.....
[46] => Array
(
[stop_sequence] => 46
[stop_id] => 122052
)
[47] => Array
(
[stop_sequence] => 47
[stop_id] => 136208
)
[48] => Array
(
[stop_sequence] => 48
[stop_id] => 128163
)
)
[12U_S_141_57_6_141] => Array
(
[1] => Array
(
[stop_sequence] => 1
[stop_id] => 1601394
)
.....
[12] => Array
(
[stop_sequence] => 12
[stop_id] => 122052
)
[13] => Array
(
[stop_sequence] => 13
[stop_id] => 136208
)
[14] => Array
(
[stop_sequence] => 14
[stop_id] => 128163
)
)
)
As you can see, both array end are equal... 35 = 1, 46 = 12, ..., 48 = 14. By equal, I mean the same stop_id but will always be diffrent for stop_sequence and of course the array entry number.
I want to know how I can compare the entire array against the other so I can know if, here let's say, the second array match the first one at 100% (except we don't look for stop_sequence so this can be different. So in this case, both will be mark as "equal", but if let's say the last entry had a different stop_id (entry 48 would be != from the entry 14), the array will be mark as "not equal".
Anyone have a path to lead me ? I keep thinking but do not know how. I've tryed array_compare but this leaded to nothing :\
Thanks
EDIT
Nothing can be change to the database. Also, the array need to be created this way (with weird text, ie 12U_S_136_15_29_141). I can do whatever in PHP.
fetch the stop_id in to new array:s and compare thous
here is a useful function
function sub_array($array, $sub_key)
{
$new_array = array();
if(is_array($array) AND $array)
{
foreach($array as $key => $data)
{
$new_array[$key] = $data[$sub_key];
}
}
return $new_array;
}
then just compare the arrays
if(sub_array($a['12U_S_136_15_29_141'], 'stop_id') == sub_array($a['12U_S_141_57_6_141'], 'stop_id'))
or if you know what stop_id that matches:
$first_stop_id_list = sub_array($a['12U_S_136_15_29_141'], 'stop_id');
$secound_stop_id_list = sub_array($a['12U_S_141_57_6_141'], 'stop_id');
$matches = array_intersect($first_stop_id_list, $secound_stop_id_list);
if(!$matches)
echo "No stop_id matches";
else if($first_stop_id_list = $secound_stop_id_list)
echo "all element was in both";
else if($matches == $first_stop_id_list)
echo "all element in first was in secound";
else if($matches == $secound_stop_id_list)
echo "all element in secound was in first";

Merge arrays together based on different values

I am having trouble thinking of the logic with the following problem:
I have the following array (has been snipped, as its much larger)
Array
(
[0] => Array
(
[code] => LAD001
[whqc] => GEN
[stocktag] => NONE
[qty] => 54
)
[1] => Array
(
[code] => LAD001
[whqc] => GEN
[stocktag] => NONE
[qty] => 6
)
[2] => Array
(
[code] => LAD004
[whqc] => HOLD
[stocktag] => NONE
[qty] => 6
)
)
I basically need to comebine all the keys in this array so that where the code, whqc and stocktag are the same, add the qty values together. With the example below, I need to end up with this:
Array
(
[0] => Array
(
[code] => LAD001
[whqc] => GEN
[stocktag] => NONE
[qty] => 60
)
[1] => Array
(
[code] => LAD004
[whqc] => HOLD
[stocktag] => NONE
[qty] => 6
)
)
As the first and second keys of the array had the same code, whqc and stocktag, the qty's have been added together into the one key.
Any ideas?
I would suggest combining the group values in to a hash, storing the full array under the hash as a key and if you have a duplicate, add the quantity, then do array_values() to pull the results.
$aggregated = array();
foreach ($records as $cRec) {
// The separator | has been used, if that appears in the tags, change it
$cKey = md5($cRec['code'] . '|' . $cRec['whqc'] . '|' . $cRec['stocktag']);
if (array_key_exists($cKey, $aggregated)) {
$aggregated[$cKey]['qty'] += $cRec['qty'];
} else {
$aggregated[$cKey] = $cRec;
}
}
// Reset the keys to numerics
$aggregated = array_values($aggregated);
I would try something like:
$output = array();
foreach($array as $details){
//make distinct key
$key = $details['code'].'_'.$details['whqc'];
if(!isset($output[$key])){
$output[$key] = $details;
}else{
$output[$key]['qty'] += $details['qty'];
$output[$key]['stocktag'] = $details['stocktag'];
}
}
$output = array_values($output);
print_r($output);
update: Orbling was first ;-)

Cakephp: question about saveall() with multiselect

I'm wondering what the cleanest way is to implement a cakephp form where 1 control is a multi-select and the rest are text fields or single-selects, and then the data is inserted as multiple rows with a saveall(). So for example a form is selected with these values:
textfield A
value=Foo
mulit-select B
values=US,Mexico,Canada
single=select C
value=10
and so I want to insert these rows into the database with a saveall():
Foo,US,10
Foo,Mexico,10
Foo,Canada,10
Now I know in the add view I can use this format for the input statement:
input('Model.0.field1',...)
but I'm wondering if I can mix that in that same form with inputs formatted like
input('Model.field2',....).
Update:
When I mix and match the single-select and multiple-select controls, the form data gets submitted like this:
Array
(
[Alert] => Array
(
[schedule_id] => 75
[user_id] => 6
[0] => Array
(
[frequency] => Array
(
[0] => WEEKLY
[1] => MONTHLY
)
)
[limit_value] => .03
[limit_adjustment] => 0
[type] => LIMIT
[disabled] => 0
)
)
I tried passing that data into saveall() but it treats it like a single record.
Update2: I think saveAll() requires that the multiple rows of data be formatted like this:
Array
(
[Article] => Array(
[0] => Array
(
[title] => title 1
)
[1] => Array
(
[title] => title 2
)
)
)
So it looks like after the submit I'm going to need some javascript code that will restructure the array.
I have something that works... I'm not sure if it takes full advantage of all of cake's "automagic" capabilities, but I don't think it's too convoluted.
So I just added the following code to my controller's add function:
if (!empty($this->data)) {
//debug($this->data, true);
/* begin custom code */
$multiselect = $this->data['Alert']['entity_id'];
$tmp2 = array();
foreach ($multiselect as $item)
{
$tmp = $this->data['Alert'];
$tmp['entity_id'] = $item;
array_push($tmp2,$tmp);
}
$this->data['Alert'] = $tmp2;
debug($this->data,true);
/* end custom code */
$this->Alert->create();
//restructure data
if ($this->Alert->saveAll($this->data['Alert'])) {
$this->Session->setFlash(__('The alert has been saved', true));
//$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The alert could not be saved. Please, try again.', true));
}
and that converts my data to this:
Array
(
[Alert] => Array
(
[0] => Array
(
[schedule_id] => 74
[entity_id] => 1
[user_id] => 6
[frequency] => HOURLY
[limit_value] => .02
[limit_adjustment] => 0
[type] => LIMIT
[disabled] => 1
)
[1] => Array
(
[schedule_id] => 74
[entity_id] => 2
[user_id] => 6
[frequency] => HOURLY
[limit_value] => .02
[limit_adjustment] => 0
[type] => LIMIT
[disabled] => 1
)
)
)

Categories