Ok so i have a post that looks kind of this
[optional_premium_1] => Array
(
[0] => 61
)
[optional_premium_2] => Array
(
[0] => 55
)
[optional_premium_3] => Array
(
[0] => 55
)
[premium_1] => Array
(
[0] => 33
)
[premium_2] => Array
(
[0] => 36 )
[premium_3] => Array
(
[0] => 88 )
[premium_4] => Array
(
[0] => 51
)
how do i get the highest number out of the that. So for example, the optional "optional_premium_" highest is 3 and the "premium_" optional the highest is 4. How do i find the highest in this $_POST
You could use array_key_exists(), perhaps something like this:
function getHighest($variableNamePrefix, array $arrayToCheck) {
$continue = true;
$highest = 0;
while($continue) {
if (!array_key_exists($variableNamePrefix . "_" . ($highest + 1) , $arrayToCheck)) {
$continue = false;
} else {
highest++;
}
}
//If 0 is returned than nothing was set for $variableNamePrefix
return $highest;
}
$highestOptionalPremium = getHighest('optional_premium', $_POST);
$highestPremium = getHighest('premium', $_POST);
I have 1 question with 2 parts before I answer, and that is why are you using embedded arrays? Your post would be much simpler if you used a standard notation like:
$_POST['form_input_name'] = 'whatever';
unless you are specifically building this post with arrays for some reason. That way you could use the array key as the variable name and the array value normally.
So given:
$arr = array(
"optional_premium_1" => "61"
"optional_premium_2" => "55"
);
you could use
$key = array_keys($arr);
//gets the keys for that array
//then loop through get raw values
foreach($key as $val){
str_replace("optional_premium_", '', $val);
}
//then loop through again to compare each one
$highest = 0;
for each($key as $val){
if ((int)$val > $highest) $highest = (int)$val;
}
that should get you the highest one, but then you have to go back and compare them to do whatever your end plan for it was.
You could also break those into 2 separate arrays and assuming they are added in order just use end() http://php.net/manual/en/function.end.php
Loop through all POST array elements, pick out elements having key names matching "name_number" pattern and save the ones having the largest number portion of the key names. Here is a PHP script which does it:
<?php // test.php 20110428_0900
// Build temporary array to simulate $_POST
$TEMP_POST = array(
"optional_premium_1" => array(61),
"optional_premium_2" => array(55),
"optional_premium_3" => array(55),
"premium_1" => array(33),
"premium_2" => array(36),
"premium_3" => array(88),
"premium_4" => array(51),
);
$names = array(); // Array of POST variable names
// loop through all POST array elements
foreach ($TEMP_POST as $k => $v) {
// Process only elements with names matching "word_number" pattern.
if (preg_match('/^(\w+)_(\d+)$/', $k, $m)) {
$name = $m[1];
$number = (int)$m[2];
if (!isset($names[$name]))
{ // Add new POST var key name to names array
$names[$name] = array(
"name" => $name,
"max_num" => $number,
"key_name" => $k,
"value" => $v,
);
} elseif ($number > $names[$name]['max_num'])
{ // New largest number in key name.
$names[$name] = array(
"name" => $name,
"max_num" => $number,
"key_name" => $k,
"value" => $v,
);
}
}
}
print_r($names);
?>
Here is the output from the script:
Array
(
[optional_premium] => Array
(
[name] => optional_premium
[max_num] => 3
[key_name] => optional_premium_3
[value] => Array
(
[0] => 55
)
)
[premium] => Array
(
[name] => premium
[max_num] => 4
[key_name] => premium_4
[value] => Array
(
[0] => 51
)
)
)
Though ineffective, you could try something like
$largest = 0;
foreach($_POST as $key => $value)
{
$len = strlen("optional_premium_");
$num = substr($key, $len);
if($num > $largest)
$largest = $num;
}
print_r($largest);
The problem being that this will only work for one set of categories. It will most likely give errors throughout the script.
Ideally, you would want to reorganize your post, make each array be something like
[optional_premium_1] => Array
(
[0] => 61
["key"] => 1
)
[optional_premium_2] => Array
(
[0] => 61
["key"] => 2
)
Then just foreach and use $array["key"] to search.
Related
I have the following working code that from 2 separate arrays ($I & $f) creates final multidimension array with the data as associated columns.
The problem is i feel the code is clunky, but i cant see if, or how it could me improved. So I'm hoping a second pair of eyes can help.
<?php
//main array of input data
$i = [ 'input_tickettype1_storeno_00' => null,
'input_tickettype1_deliverydate_00' => null,
'input_tickettype1_ticketref_00' => null,
'input_tickettype1_storeno_01' => '9874',
'input_tickettype1_deliverydate_01' => '2022-02-01',
'input_tickettype1_ticketref_01' => 'EDN6547',
'input_tickettype1_storeno_02' => '8547',
'input_tickettype1_deliverydate_02' => '2022-01-31',
'input_tickettype1_ticketref_02' => 'EDN5473',
'input_tickettype1_storeno_03' => '9214',
'input_tickettype1_deliverydate_03' => '2022-02-28',
'input_tickettype1_ticketref_03' => 'EDN1073'
];
//headers
$h = [ 'input_tickettype1_storeno' ,
'input_tickettype1_deliverydate',
'input_tickettype1_ticketref'
];
//final multidim array
$f = array();
//Create a multidim for the headers and the values
foreach ($h as $k => $v)
{
$f[] = [$v=>null];
}
//loop throught the headers looping for matches in the input data
for ($x = 0; $x < count($f); $x++) {
foreach ($f[$x] as $fk => $fv) {
foreach ($i as $ik => $iv) {
if (str_contains($ik,$fk)) {
array_push($f[$x],$iv);
}
}
}
}
print_r($f);
//Actual Working Output
// Array (
// [0] => Array ( [input_tickettype1_storeno] =>
// [0] =>
// [1] => 9874
// [2] => 8547
// [3] => 9214
// )
// [1] => Array ( [input_tickettype1_deliverydate] =>
// [0] =>
// [1] => 2022-02-01
// [2] => 2022-01-31
// [3] => 2022-02-28
// )
// [2] => Array ( [input_tickettype1_ticketref] =>
// [0] =>
// [1] => EDN6547
// [2] => EDN5473
// [3] => EDN1073
// )
// )
?>
Yes, indeed I think the code can be optimised for readability and logic.
I can think of two methods you can use.
Method 1 : nested foreach
First of all, you don't need a foreach to initialize your multidimentional array, you can do it within the main loop you use to read the data. So you can remove the foreach -- $f[] = [$v=>null];
Then, instead of having 1 for and 2 foreach you can just have 2 foreach one for each array and use a very fast strpos to identify if the key matches and populate the final array.
Here's the resulting code.
$f = [];
foreach ($h as $prefix) {
$f[$prefix] = [];
foreach ($i as $key => $val) {
if (strpos($key, $prefix) === 0) {
$f[$prefix][] = $val;
}
}
}
This first method is simple, with a straightforward logic. However it requires a nested foreach. Which means that if both arrays get larger, your code gets much slower.
Method 2 : key manipulation
This method assumes that the keys of the first array never change structure and they are always somestringid_[digits]
In this case we can avoid looping the second array and just use a regular expression to recreate the key.
$f = [];
foreach ($i as $key => $value) {
preg_match('/^(.*)_[0-9]+$/', $key, $m);
$key = $m[1];
if (empty($f[$m[1]])) {
$f[$m[1]] = [];
}
$f[$m[1]][] = $value;
}
I don't see any need to implement any additional data or conditions. You only need to read your main array, mutate the keys (trim the trailing unique identifiers) as you iterate, and push data into their relative groups.
Code: (Demo)
$result = [];
foreach ($array as $k => $v) {
$result[preg_replace('/_\d+$/', '', $k)][] = $v;
}
var_export($result);
Output:
array (
'input_tickettype1_storeno' =>
array (
0 => NULL,
1 => '9874',
2 => '8547',
3 => '9214',
),
'input_tickettype1_deliverydate' =>
array (
0 => NULL,
1 => '2022-02-01',
2 => '2022-01-31',
3 => '2022-02-28',
),
'input_tickettype1_ticketref' =>
array (
0 => NULL,
1 => 'EDN6547',
2 => 'EDN5473',
3 => 'EDN1073',
),
)
I have an array like this:
Array
(
[1] => Array
(
[uris] => Array
(
[1] => /
[2] => /news/
[3] => /about/
[4] => /contact/
)
[templates] => Array
(
[1] => 1
[2] => 2
[3] => 3
[4] => 4
)
)
)
and I need to update all the IDs with a new set of values so the final output should be something like:
[uris] => Array
(
[100] => /
[101] => /news/
[102] => /about/
[103] => /contact/
)
[templates] => Array
(
[100] => 1
[101] => 2
[102] => 3
[103] => 4
)
I think I might need to use a regex pattern like '/(\[.*?\])/' but I'm not sure how to put it together to get the final updated output.
EDIT: I should mention that the IDs I'm updating to won't be in sequential order, they're coming from a database table of entries in a CMS. Entries are being duplicated so they'll have the same URIs but the second set with have a higher set of IDs than the original ones.
There won't be a rule for the second set of IDs. The only guarantee is that the second set will all be higher than the highest ID from the first set.
The CMS I'm working with allows me to duplicate entries for use on a second site. But the CMS also uses a third party module that creates a serialized array like I've posted above which matches URIs against templates. The module doesn't create a new serialized array of the new entry IDs when the entries get duplicated, so what's I'm trying to do manually.
I thought I could unserialize the array, update the string's old IDs with the corresponding IDs of the new entries, reserialize it, and then copy it back into the database.
Array (
[1] => /
[2] => /news/
[3] => /about/
[4] => /contact/
)
Given this kind of array, what you need to do to replace the keys is simply:
$array = array_combine(range(100, 100 + (count($array) - 1)), $array);
It generates keys [100, .., 103] and splices them into the array.
You might have to loop and then replace the keys :
foreach ($yourArray as $array) {
for ($i = 0; $i < count($array['uris']); $i++) {
$array['uris'][$i][$newkey] = $array['uris'][$i][$oldkey];
unset($array['uris'][$i][$oldkey]);
}
for ($i = 0; $i < count($array['templates']); $i++) {
$array['templates'][$i][$newkey] = $array['templates'][$i][$oldkey];
unset($array['templates'][$i][$oldkey]);
}
}
As per your question update; not too sure what you're trying to do, but I have two guesses.
arr2d_replace_id will take all the uris and increase key and also a new set of array with updated keys and it's value.
arr2d_replace_id2 will 1) flip array of templates - where I'm guessing the value represents the ID of route in uris and so flipped to preserve values; 2) increase key value on uris; 3) change flipped array's value according to the key based on uris; 4) flip the array back with the new set info and assign to result.
function arr2d_replace_id($arr, $inc) {
$result = array();
foreach ($arr['uris'] as $k=>$v) {
$result['uris'][intval($k) + $inc] = $v;
$result['templates'][intval($k) + $inc] = $arr['templates'][$k];
}
return $result;
}
function arr2d_replace_id2($arr, $inc) {
$result = array();
$tpl_flipped = array_flip($arr['templates']);
foreach ($arr['uris'] as $k=>$v) {
$result['uris'][intval($k) + $inc] = $v;
$tpl_flipped[$k] = intval($k) + $inc;
}
$result['templates'] = array_flip($tpl_flipped);
return $result;
}
$test = array(
'uris' => array(
1 => '/', '/news/', '/about/', '/contact/',
),
'templates' => array(
1 => 1, 2, 3, 4
)
);
print_r( $test );
print_r( arr2d_replace_id($test, 100) );
print_r( arr2d_replace_id2($test, 100) );
See in action: http://3v4l.org/T6hHD
If the array values are unique, you can use array_flip:
$array = [
1 => '/',
2 => '/contact/',
3 => '/about/'
];
$counter = 100;
$array = array_flip($array);
$array = array_map(function($oldKey) use (&$counter) {
return ++$counter;
}, $array);
$array = array_flip($array);
$mainArray = array();
$mainArray[]=array("uris" => array("/", '/news', '/about', '/contact') , "templates" => array(1,2,3,4));
foreach ($mainArray as &$array) {
$uris = $array['uris'];
$keys = array_keys($uris);
for($i=0;$i<count($keys);$i++)
{
$uris[$keys[$i] + 100]=$uris[$i];
unset($uris[$i]);
}
$template = $array['templates'];
$keys = array_keys($uris);
for($i=0;$i<count($keys);$i++)
{
$template[$keys[$i] + 100]=$template[$i];
unset($template[$i]);
}
$array['uris'] = $uris;
$array['templates'] = $template;
}
echo "<pre>";
print_r($mainArray);
exit;
Try this one,
$array = array(
array('uris' => array(
'1' => '/',
'2' => '/news/',
'3' => '/about/',
'4' => '/contact/'
),
'templates' => array
(
'1' => '1',
'2' => '2',
'3' => '3',
'4' => '4'
)
)
);
$val = 100;
$result = array();
foreach ($array as $key => $value) {
foreach ($value as $key1 => $value1) {
foreach ($value1 as $key2 => $value2) {
$result[$key][$key1][$val] = $value2;
$val++;
}
}
}
var_dump($result);
I am having a terrible time getting this to work I have been struggling with it for a couple hours now. Can someone please help me? I have included a fiddle.
I believe my problem is in this string:
$$salesAndOwner[$i]["$salesAndOwner[$i]".$l] = $salesAndOwner[$i.$l][$param] = $values[$l];
Basically I have the following multidimensional array:
[sales] => Array
(
[FirstName] => Array
(
[0] => salesFirst1
[1] => salesFirst2
)
[LastName] => Array
(
[0] => salesLast1
[1] => salesLast2
)
)
[decisionmaker] => Array
(
[FirstName] => Array
(
[0] => dmFirst1
[1] => dmFirst2
)
[LastName] => Array
(
[0] => dmLast1
[1] => dmLast2
)
)
)
I need this to be reorganized like I did with the following array:
Array
(
[additionallocations0] => Array
(
[Address] => Address1
[State] => State1
)
[additionallocations1] => Array
(
[Address] => Address2
[State] => State2
)
)
Here is the original:
Array
(
[additionallocations] => Array
(
[Address] => Array
(
[0] => Address1
[1] => Address2
)
[State] => Array
(
[0] => State1
[1] => State2
)
)
This is how I reorganize the above array:
if(isset($_POST['additionallocations'])) {
$qty = count($_POST['additionallocations']["Address"]);
for ($l=0; $l<$qty; $l++)
{
foreach($_POST['additionallocations'] as $param => $values)
{
$additional['additionallocations'.$l][$param] = $values[$l];
}
}
And this is what I am using for the sales and decisionmaker array. If you notice I have an array that contains sales and decisionmaker in it. I would like to be able to sort any future arrays by just adding its primary arrays name. I feel I am close to solving my problem but I can not get it to produce right.
$salesAndOwner = array(0 => "sales", 1 => "decisionmaker");
for($i = 0; $i < 2; $i++){
$qty = count($_POST[$salesAndOwner[$i]]["FirstName"]);
for ($l=0; $l<$qty; $l++)
{
foreach($_POST[$salesAndOwner[$i]] as $param => $values)
{
$$salesAndOwner[$i]["$salesAndOwner[$i]".$l] = $salesAndOwner[$i.$l][$param] = $values[$l];
}
}
}
In the above code I hard coded 'sales' into the variable I need it to make a variable name dynamically that contains the sales0 decisionmaker0 and sales1 decisionmaker1 arrays so $sales and $decisionmaker
I hope this makes sense please let me know if you need any more info
Let's break it down. Using friendly variable names and spacing will make your code a lot easier to read.
Remember. The syntax is for you to read and understand easily. (Not even just you, but maybe future developers after you!)
So you have an array of groups. Each group contains an array of attributes. Each attribute row contains a number of attribute values.
PHP's foreach is a fantastic way to iterate through this, because you will need to iterate through (and use) the index names of the arrays:
<?php
$new_array = array();
// For each group:
foreach($original_array as $group_name => $group) {
// $group_name = e.g 'sales'
// For each attribute in this group:
foreach($group as $attribute_name => $attributes) {
// $attribute_name = e.g. 'FirstName'
// For each attribute value in this attribute set.
foreach($attributes as $row_number => $attribute) {
// E.g. sales0
$row_key = $group_name . $row_number;
// if this is the first iteration, we need to declare the array.
if(!isset($new_array[$row_key])) {
$new_array[$row_key] = array();
}
// e.g. Array[sales0][FirstName]
$new_array[$row_key][$attribute_name] = $attribute;
}
}
}
?>
With this said, this sort of conversion may cause unexpected results without sufficient validation.
Make sure the input array is valid (e.g. each attribute group has the same number of rows per group) and you should be okay.
$salesAndOwner = array("sales", "decisionmaker");
$result = array();
foreach ($salesAndOwner as $key) {
$group = $_POST[$key];
$subkeys = array_keys($group);
$first_key = $subkeys[0];
foreach ($group[$first_key] as $i => $val) {
$prefix = $key . $i;
foreach ($subkeys as $subkey) {
if (!isset($result[$prefix])) {
$result[$prefix] = array();
}
$result[$prefix][$subkey] = $val;
}
}
}
DEMO
Try
$result =array();
foreach($arr as $key=>$val){
foreach($val as $key1=>$val1){
foreach($val1 as $key2=>$val2){
$result[$key.$key2][$key1] = $val2;
}
}
}
See demo here
The question is simple, let's suppose that I have an array like:
$array = array(array('bla1' => 'bla1'), array('bla2' => 'bla2'),
array('bla3' => 'bla3'), array('bla4' => 'bla4'));
Yeah it's multi-dimensional so I need to set value between e.g. array('bla1' => 'bla1') and array('bla2' => 'bla2') without erasure.
I was puzzled to find, through all array_ like functions in php how to do this.
So, as any other programmer would do, I wrote the function:
function setArrVal($array, $key, $val) {
for ($i = count($array) - 1; $i >= $key; $i--) {
$array[$i + 1] = $array[$i];
}
$array[$key] = $val;
return $array;
}
Works well.
But still need to do this with php function, is there any way to complete this that way?
I've tried array_splice($input, 1, 0, $replacement); - worthless, it's only working with simple values, not with arrays in array.
You can use array_splice() like so:
$array = array(array('bla1' => 'bla1'), array('bla2' => 'bla2'),
array('bla3' => 'bla3'), array('bla4' => 'bla4'));
$insert = array(array('bla2.5' => 'bla2.5'));
// note the third argument argument is 0
// this will prevent it from overwriting existing values
array_splice($array, 2, 0, $insert );
print_r($array);
/* Result */
Array
(
[0] => Array
(
[bla1] => bla1
)
[1] => Array
(
[bla2] => bla2
)
[2] => Array
(
[bla2.5] => bla2.5
)
[3] => Array
(
[bla3] => bla3
)
[4] => Array
(
[bla4] => bla4
)
)
Demo: http://codepad.org/ivBmZRdn
Is this what you wanted?
I have searched around and I am at my wits end so I will make this easy. This is what I have in a print_r:
Array
(
[0] => Array
(
[name] => client interaction
[y] => 2.7
)
[1] => Array
(
[name] => client interaction
[y] => 0.1
)
[2] => Array
(
[name] => project planning
[y] => 0.1
)
[3] => Array
(
[name] => client interaction
[y] => 5.9
)
)
And this is what I want it to be:
Array
(
[0] => Array
(
[name] => client interaction
[y] => 8.7
)
[1] => Array
(
[name] => project planning
[y] => 0.1
)
)
Is it absolutely necessary that your desired array use numeric indeces? If I were to do this I would do it this way (not the same as your desired array though)
$newArray = array();
foreach($array as $item)
{
if(!isset($newArray[$item["name"]]))
$newArray[$item["name"]] = 0;
$newArray[$item["name"]] += $item["y"];
}
This will give you an array of this structure:
Array
(
[client interaction] => 8.7
[project planning] => 0.1
)
To get the keys back you simply use the second form of the foreach loop
foreach($newArray as $name => $y)
$name will contain the name and $y the y in your original array.
$hash = array();
foreach ($sourceArray as $key=>$value) {
$y = 0;
if (isset($hash{$value{'name'}})) {
$y = $hash{$value{'name'}};
}
$hash{$value{'name'}} = $y + $value{'y'};
}
$result = array();
foreach ($hash as $key => $value) {
$result[] = array( 'name' => $key, 'value' => $value );
}
print_r($result);
The last loop is just to get $hash into the exact format you specified.
Explanation:
$hash
Is a temporary structure used to compute the sums for each unique name.
foreach ($sourceArray as $key=>$value) {
This goes through your original array ($sourceArray) and pulls out each element.
$y = 0;
Initializes a variable to store the current sum that belongs with that name.
if (isset($hash{$value{'name'}})) {
Checks to see if a value has already been stored in $hash for the given name.
$y = $hash{$value{'name'}};
}
Sets $y to the previously calculated sum for the given name, if there was one.
$hash{$value{'name'}} = $y + $value{'y'};
}
Stores the sum for the given name into our temporary structure $hash.
$result = array();
foreach ($hash as $key => $value) {
$result[] = array( 'name' => $key, 'value' => $value );
}
converts $hash to the format you desired.
The empy []'s in $result[] = ... add the right hand side of the expression to the end of the $result array.
$mixed = array(); // Should contain your array shown above
$groups = array();
$newArray = array(); // Will contain your new array
$counter = 0;
foreach( $mixed as $mix )
{
if ( isset($groups[$mix['name']]) )
{
$newArray[$groups[$mix['name']]]['y'] += $mix['y'];
}
else
{
$groups[$mix['name']] = $counter;
$newArray[] = $mix;
$counter++;
}
}
http://codepad.org/EjdHxgvt