How can I achieve this in Array in PHP - php

am having problem achieving this result with array, I want to update another empty array with data in first array in such a way that the first two rows is ommitted and the first 3rows is added to the index 0 of the empty array, and the next 3 rows is also updated to the second index and so on. I have this Array in
`$arr = [
'tqty' => 9,
'tPrice' => 18700,
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000,
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000
];`
I want to use this array data and update another empty array this way, removing the first two rows
$arr2 = [
0 => [
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000
],
1 => [
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000
]
];
here is my code so far
$arr = [
'tqty' => 9,
'tPrice' => 18700,
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000,
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000
];
$newdat = [];
$count = 0;
$oldcount = 1;
foreach($arr as $key => $value){
if(preg_match_all('!\d+!', $key, $matches)){
if($oldcount == $matches[0][0]){
$newdat[$matches[0][0]] = [
$count => [
$key => $value
]
];
} else{
$count = 0;
$oldcount = $matches[0][0];
}
}
$count++;
}
I hope I get help soon. thanks

Assuming the array keys and order stay consistent you could use array_chunk
<?php
$inArray = [
'tqty' => 9,
'tPrice' => 18700,
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000,
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000,
];
$outArray = [];
// Remove first 2 values.
$inArray = array_slice( $inArray, 2 );
// 'Chunk' the rest of the values.
// true preserves keys.
$outArray = array_chunk( $inArray, 3, true );
echo '<pre>' . print_r( $outArray, true ) . '</pre>';
/**
Output:
<pre>Array
(
[0] => Array
(
[food_name_1] => Black Coffee
[food_quanty_1] => 1
[food_price_1] => 1000
)
[1] => Array
(
[food_name_2] => Sub Combo
[food_quanty_2] => 2
[food_price_2] => 3000
)
)
</pre>
*/

If I have understood you correctly,
$newdata = array();
for ($i = 1; $i++;) { // Intentionally no condition set.
if (array_key_exists('food_name_' . $i, $arr)) {
$temparray = array();
$temparray['food_name_' . $i] = $arr['food_name_' . $i];
if (array_key_exists('food_quanty_' . $i, $arr)) {
$temparray['food_quanty_' . $i] = $arr['food_quanty_' . $i];
}
if (array_key_exists('food_price_' . $i, $arr)) {
$temparray['food_price_' . $i] = $arr['food_price_' . $i];
}
$newdata[] = $temparray;
} else {
break; // break out of the loop
}
}
echo "<pre>";
print_r($newdata);
echo "</pre>";
die();

Loop through it and build the array index string via variables.
<?php
$arr = [
'tqty' => 9,
'tPrice' => 18700,
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000,
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000
];
foreach(array("food_name_","food_quanty_","food_price_") as $v){
// replace the set value of 2 here with a count() on the $arr
// and some basic math - IF you are always sure you'll have 3 fields
for($i=0;$i<2;$i++){
$newarr[$i][$v.($i+1)]=$arr[$v.($i+1)];
}
}
print_r($newarr);
?>

Here's a solution that will locate the _x at the end to check its a digit
This solution does not worry about how many non numbered fields you have, or how many fields there are per numbered "row", they are also indexed based on the _x number.
$arr = [
'tqty' => 9,
'tPrice' => 18700,
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000,
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000
];
$arr2 = array();
foreach( $arr as $key => $value )
{
$explode = explode( '_', $key );
if( ctype_digit( $index = end( $explode ) ) === true)
{
if( isset( $arr2[ $index ] ) === false )
{
$arr2[ $index ] = array();
}
$arr2[ $index ][ substr( $key, 0, strlen( $key ) - 1 - strlen( $index ) ) ] = $value;
}
}
print_r( $arr2 );
Output:
Array
(
[1] => Array
(
[food_name] => Black Coffee
[food_quanty] => 1
[food_price] => 1000
)
[2] => Array
(
[food_name] => Sub Combo
[food_quanty] => 2
[food_price] => 3000
)
)

If you already know that you need always the same indexes from $arr, you can use the array_keys function in order to index the associative array.
Example:
$keys = array_keys($arr);
echo '<br><br>'.$arr[$keys[1]];
Here is a complete example:
$keys = array_keys($arr); #stores the associative keys by index
$arr2 = array();
/* For each array $arr do the following */
$limit = 5; #substitute this with: count($arraylist)
for( $n_array=0; $n_array<limit; $n_array++ ){
$cur_arr = array(); #substitute with your: $arraylist[ $n_array ]
for( $a = 2; $a<count($arr); $a++ ){
$cur_arr[ $keys[$a] ] = $arr[ $keys[$a] ];
}
$arr2[ $n_array ] = $cur_arr;
}
Hope it will be helpful

Related

arrays with dif keys inside 1 array

like the question says, I have 2 foreach cycles, 1 cycle iterates an array with 4 keys, and the other one an array with 3 keys, how to get this two arrays in only 1 ?
I have this
....
],
],
'Detalle' => array()
];
foreach ($datos["line_items"] as $line => $item) {
$tempArray = array(
'NmbItem' => $item['name'],
'QtyItem' => $item['quantity'],
'PrcItem' => $item['price'],
'IndExe' => 1
);
}
foreach($datos["fee_lines"] as $line => $fee){
$tempArray=array(
'NmbItem' => $fee['name'],
'QtyItem' => 1,
'PrcItem' => $fee['total']
);
}
$dte['Detalle'][] = $tempArray;
}
if you notice the second array cycle doesnt contain 'indexe' key, after asign this tempArray in $dte['Detalle'][] = $tempArray only works with the last cycle, or the first one if I remove the second.
the output should be something like:
temp = Array (
array[0]
'NmbItem => name',
'QtyItem'=> 10,
'PrcItem'= 1000,
'IndExe' => 1
array[1]
'NmbItem => another name',
'QtyItem'=> 5,
'PrcItem'=> 3000
)
To make it work with your code, you should also add $dte['Detalle'][] = $tempArray; after the first loop.
The issue is that you are setting the $tempArray in each foreach so you end up with only the last one when assigning it in the $dte['Detalle'].
So, something like this should work:
foreach ($datos["line_items"] as $line => $item) {
$tempArray = array(
'NmbItem' => $item['name'],
'QtyItem' => $item['quantity'],
'PrcItem' => $item['price'],
'IndExe' => 1
);
}
$dte['Detalle'][] = $tempArray;
foreach($datos["fee_lines"] as $line => $fee){
$tempArray=array(
'NmbItem' => $fee['name'],
'QtyItem' => 1,
'PrcItem' => $fee['total']
);
}
$dte['Detalle'][] = $tempArray;
However, I would do it using the array_map function.
Docs for array_map
You can have it something like this:
<?php
$data_1 = array_map(function($item){
return array(
'NmbItem' => $item['name'],
'QtyItem' => $item['quantity'],
'PrcItem' => $item['price'],
'IndExe' => 1
);
}, $datos["line_items"]);
$data_2 = array_map(function($fee){
return array(
'NmbItem' => $fee['name'],
'QtyItem' => 1,
'PrcItem' => $fee['total']
)
}, $datos["fee_lines"]);
$dte['Detalle'] = array_merge($dte['Detalle'], $data_1, $data_2);

Selecting value from array with a range?

I've an array on php that will return a lot of keys->values, like this:
Array
[0] => Array
(
[value] => 405
[information] => some information1
)
[1] => Array
(
[value] => 500
[information] => some information2
)
[2] => Array
(
[value] => 700
[information] => some information3
)
the values are numbers, i need to collect all the values, check the first one that will be >= $determinedvalue and then return the value "information" for this exactly array, is this even possible? I know i can do this if i create a temp table on my database, but i dont want to.
To be more clearly, when my value is "430" it will return me "some information2".
I've searched a lot on google but by now i dont know if this is even possible.
Appreciate any help.
This is a sample on how to do that. Comments in code can be used to explain the execution.
// Sample Array
$arr = array(
array
(
"value" => 405,
"information" => "some information1"
),
array
(
"value" => 500,
"information" => "some information2"
),
array
(
"value" => 700,
"information" => "some information3"
)
);
// Sample Number
$numberToCheck = 430;
// Sub Array To Assign
$subArray = array();
// Loop Through Outer Array
for ( $i = 0; $i < sizeof($arr); $i++)
{
// If Value In Array > Number Check
if ( $arr[$i]['value'] >= $numberToCheck )
{
$subArray = $arr[$i]; // Assign Sub Array
$i = sizeof($arr); // This is Used to Exit For Loop
}
}
print_r($subArray); // Print
Working runnable code: https://tech.io/snippet/QJ93AwV
Code snippent with comments:
<?php
/**
* Helper class for stable sort alogithms
* #see https://github.com/vanderlee/PHP-stable-sort-functions
* Class StableSort
*/
class StableSort
{
static public function usort(array &$array, $value_compare_func)
{
$index = 0;
foreach ($array as &$item) {
$item = array($index++, $item);
}
$result = usort($array, function ($a, $b) use ($value_compare_func) {
$result = call_user_func($value_compare_func, $a[1], $b[1]);
return $result == 0 ? $a[0] - $b[0] : $result;
});
foreach ($array as &$item) {
$item = $item[1];
}
return $result;
}
}
$array = [
// added for test sorting
[
'value' => 9999,
'information' => 'some information-1',
],
[
'value' => 1200,
'information' => 'some information0',
],
// \added for test sorting
[
'value' => 405,
'information' => 'some information1',
],
// added for test sorting stability
[
'value' => 405,
'information' => 'some information1.2',
],
[
'value' => 405,
'information' => 'some information1.1',
],
// \added for test sorting stability
[
'value' => 500,
'information' => 'some information2',
],
[
'value' => 700,
'information' => 'some information3',
],
];
// sort array
$determinedvalue = 430;
StableSort::usort($array, function ($item1, $item2) {
if ($item1['value'] == $item2['value']) return 0;
return $item1['value'] < $item2['value'] ? -1 : 1;
});
// then select the first element by condition
$res = null;
foreach($array as $v) {
if($v['value'] >= $determinedvalue) {
$res = $v['information'];
break;
}
}
// for testing
print $res;
$number = 430;
$array = Array
[0] => Array
(
[value] => 405
[information] => some information1
)
[1] => Array
(
[value] => 500
[information] => some information2
)
[2] => Array
(
[value] => 700
[information] => some information3
)
$firstArray = $array[0];
$secondArray = $array[1];
$threeArray = $array[2];
function selectValueFromArrayRange ($number, $start, $end, $value, $infomation)
{
$startValue = $start[$value];
$endValue = $end[$value];
if ( in_array($number, range($startValue, $endValue)) ) {
return $end[$infomation];
}
}
selectValueFromArrayRange($number, $firstArray, $secondValue, 'value', 'infomation')

PHP : multidimensional array merge recursive

I need to merge those two arrays:
$ar1 = array("color" => array("red", "green"), "aa");
$ar2 = array("color" => array( "green", "blue"), "bb");
$result = array_merge_recursive($ar1, $ar2);
Expected output:
[
'color' => [
(int) 0 => 'red',
(int) 1 => 'green',
(int) 3 => 'blue'
],
(int) 0 => 'aa',
(int) 1 => 'bb'
]
But it outputs:
[
'color' => [
(int) 0 => 'red',
(int) 1 => 'green',
(int) 2 => 'green', (!)
(int) 3 => 'blue'
],
(int) 0 => 'aa',
(int) 1 => 'bb'
]
I'm looking for the simplest way to do this, my array inputs won't be deeper than those examples.
Here it is.
function array_merge_recursive_ex(array $array1, array $array2)
{
$merged = $array1;
foreach ($array2 as $key => & $value) {
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
$merged[$key] = array_merge_recursive_ex($merged[$key], $value);
} else if (is_numeric($key)) {
if (!in_array($value, $merged)) {
$merged[] = $value;
}
} else {
$merged[$key] = $value;
}
}
return $merged;
}
Thanks to Meglio comment, you can use these functions for any number of arrays :
Functions
function drupal_array_merge_deep() {
$args = func_get_args();
return drupal_array_merge_deep_array($args);
}
// source : https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/drupal_array_merge_deep_array/7.x
function drupal_array_merge_deep_array($arrays) {
$result = array();
foreach ($arrays as $array) {
foreach ($array as $key => $value) {
// Renumber integer keys as array_merge_recursive() does. Note that PHP
// automatically converts array keys that are integer strings (e.g., '1')
// to integers.
if (is_integer($key)) {
$result[] = $value;
}
elseif (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
$result[$key] = drupal_array_merge_deep_array(array(
$result[$key],
$value,
));
}
else {
$result[$key] = $value;
}
}
}
return $result;
}
Usage
$merged = drupal_array_merge_deep($ar_1, $ar_2);
var_dump($merged);
$merged = drupal_array_merge_deep_array([$ar_1, $ar_2]);
var_dump($merged);
Usage (test data)
$ar_1 = [
"item1" => false,
"item2" => true,
"item_list" => [
"sub_item1" => 5,
"sub_itemlist" => [
"sub_sub_item1" => 27,
],
]
];
$ar_2 = [
"item_list" => [
"sub_item2" => 5,
"sub_itemlist" => [
"sub_sub_item2" => 27,
],
],
"item3" => true,
];
Usage output (same for both functions)
array (size=4)
'item1' => boolean false
'item2' => boolean true
'item_list' =>
array (size=3)
'sub_item1' => int 5
'sub_itemlist' =>
array (size=2)
'sub_sub_item1' => int 27
'sub_sub_item2' => int 27
'sub_item2' => int 5
'item3' => boolean true

remove duplicate array php

I have script like this
foreach ($onerow as $onekey => $dt ){
$arr = array();
foreach($row as $classkey => $classfoto):
$cek_class_foto = explode("/",$classfoto->name);
if($dt->foto_naam!=$cek_class_foto[1]){
$arr = array($dt->foto_naam);
print_r(array_unique($arr));
}
endforeach;
}
the output like this
Array ( [0] => _b101203.jpg )
Array ( [0] => _b101203.jpg )
my question is, how to remove this duplicates array?
Thank you
You are overwriting $arr for each iteration.
foreach ($onerow as $onekey => $dt ){
$arr = array();
foreach($row as $classkey => $classfoto):
$cek_class_foto = explode("/",$classfoto->name);
if($dt->foto_naam!=$cek_class_foto[1]){
$arr[] =$dt->foto_naam;
}
endforeach;
}
$arr = array_unique($arr);
$array1 = Array
(
'0' => Array
(
'messageId' => 9,
'userId' => 47,
'petId' => 68,
'message' => 'how hello',
'senderId' => 48,
'senderPetId' => 66,
'messageCreateTime' => '2015-07-31 11:44:59'
),
'1' => Array
(
'messageId' => 8,
'userId' => 49,
'petId' => 69,
'message' => 'pppppppppp',
'senderId' => 48,
'senderPetId' => 67,
'messageCreateTime' => '2015-07-31 11:15:16'
),
'2' => Array
(
'messageId' => 6,
'userId' => 48,
'petId' => 67,
'message' => 'gggg',
'senderId' => 49,
'senderPetId' => 69,
'messageCreateTime' => '2015-07-31 11:13:42'
),
'3' => Array
(
'messageId' => 2,
'userId' => 48,
'petId' => 67,
'message' => 'aaaaaaaa',
'senderId' => 47,
'senderPetId' => 68,
'messageCreateTime' => '2015-07-31 11:15:33'
)
);
/* code for removing last duplicate array within result array by KS */
/* matching between : userId, petId, senderId, senderPetId */
$temp_array = array();
$i = 0;
foreach($array1 as $key=>$value)
{
$FLAG = FALSE;
$temp_array = $array1[$key];
if($i==0)
{
$final_array[] = $temp_array;
}
else
{
for($j=0;$j<count($final_array);$j++)
{
if(($final_array[$j]['userId']==$temp_array['userId'] && $final_array[$j]['petId']==$temp_array['petId'] && $final_array[$j]['senderId']==$temp_array['senderId'] && $final_array[$j]['senderPetId']==$temp_array['senderPetId']) ||
($final_array[$j]['userId']==$temp_array['senderId'] && $final_array[$j]['petId']==$temp_array['senderPetId'] && $final_array[$j]['senderId']==$temp_array['userId'] && $final_array[$j]['senderPetId']==$temp_array['petId']))
{
$FLAG = TRUE;
}
}
if($FLAG == FALSE){
$final_array[] = $temp_array;
}
}
$i++;
}
print('<pre>');
print_r($final_array);
enter code here

Run throw array of associative array and find keys

I have two arrays that look like this:
(this one is ordered by value_max)
$max_values = [
["name" => "john", "id" => 5, "value_max" => 500],
["name" => "john", "id" => 3, "value_max" => 200],
...
];
$min_values = [
["name" => "john", "id" => 5, "value_min" => 100],
["name" => "john", "id" => 3, "value_min" => 150],
...
];
And I need to have a final array like this:
(This one stills need to be ordered by value_max, so I assume I could just overwrite the first array with the calculations done with the second)
$max_and_difference_values = [
["name" => "john", "id" => 5, "value_max" => 500, "difference_value" => 400],
["name" => "john", "id" => 3, "value_max" => 200, "difference_value" => 50 ],
...
];
My question is pretty straight: What is the best/effective way to run through both first arrays and build the last one. Assuming that the size of the arrays can be of around 150 elements.
To avoid looping through all arrays repeatedly, index one array by the field you want to merge on, i.e. the 'id' key:
$second = array_combine(array_map(function ($i) { return $i['id']; }, $second_array), $second_array);
Then looping through the other and comparing the values is pretty easy:
$third = array();
foreach ($first_array as $i) {
$third[] = $i + array('difference_value' => $i['value_max'] - $second[$i['id']]['value_min']);
}
If it's guaranteed that both arrays will have exactly matching keys, you don't even need the first step and just go by already existing keys.
This will sort your array. So you can sort the second array.
<?php
$min_values = array(
array("name" => "john", "id" => 5, "value_min" => 100),
array("name" => "john", "id" => 3, "value_min" => 150),
);
function aasort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii]=$va[$key];
}
asort($sorter);
foreach ($sorter as $ii => $va) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
}
aasort($min_values,"id");
echo "<pre>";
print_r($min_values);
echo "</pre>";
?>
And then you can use the logic what Alessandro Minoccheri mentioned.
$arr = array();
for ($i=0; $i<count($first_array);$i++){
$arr['name'] = $first_array[$i]['name'];
$arr['id'] = $first_array[$i]['id'];
$arr['value_max'] = $first_array[$i]['value_max'];
$arr['difference_value'] = $first_array[$i]['value_max']-$second[$i['id']]['value_max'] ;
}
As you have not shared how the second array with the minimum values is ordered (in itself and relative to the maximum values array), I'd say, index the minimum values by the id entry and then do the calculation in a second iteration. It should be fast enough, 150 elements is just "nothing":
$max_values = [
["name" => "john", "id" => 5, "value_max" => 500],
["name" => "john", "id" => 3, "value_max" => 200],
];
$min_values = [
["name" => "john", "id" => 5, "value_min" => 100],
["name" => "john", "id" => 3, "value_min" => 150],
];
$min_values_by_id = [];
foreach($min_values as $min) {
$min_values_by_id[$min['id']] = $min['value_min'];
}
$max_and_difference_values = $max_values;
foreach($max_and_difference_values as &$entry)
{
$entry['difference_value'] = $entry['value_max'] - $min_values_by_id[$entry['id']];
}
unset($entry);
print_r($max_and_difference_values);
This is just a straight forward example, nothing fancy. Demo
the following works for me. I'm not a PHP expert though, i.e. I'm not so familiar with cloning (note the empty clone array). Note that it only copies existing properties (if one array does contain a min_value and another does only contain a some other key)
In essence
function convertArr( $arr ) {
// Easy referencing without having to search through the arrays more than once for a matching id
$new_arr = array();
foreach( $arr as $array ) {
$new_arr[ $array['id'] ] = cloneArr( $array );
}
return $new_arr;
}
function merge( $arr1, $arr2 ) {
$convertedArr1 = convertArr( $arr1 );
$convertedArr2 = convertArr( $arr2 );
$arr = array();
// Based on the ordered array
foreach( $convertedArr1 as $array ) {
$id = $array['id'];
$tempArr = array();
foreach( $convertedArr1[ $id ] as $k => $v ) {
$tempArr[ $k ] = $v;
}
foreach( $convertedArr2[ $id ] as $k => $v ) {
$tempArr[ $k ] = $v;
}
array_push( $arr, $tempArr );
}
return $arr;
}
Full example:
<?php
//$arr1 = [ ["name" => "john", "id" => 5, "value_max" => 500], ["name" => "john", "id" => 3, "value_max" => 200] ];
//$arr2 = [ ["name" => "john", "id" => 5, "value_min" => 100], ["name" => "john", "id" => 3, "value_min" => 150] ];
$arr1 = array(
array( "name" => "john", "id" => 5, "value_max" => 500 ),
array( "name" => "john", "id" => 3, "value_max" => 200 )
);
$arr2 = array(
array( "name" => "john", "id" => 5, "value_min" => 100 ),
array( "name" => "john", "id" => 3, "value_min" => 150 )
);
function neatPrint( $arr ) {
echo "<pre>";
print_r( $arr );
echo "</pre>";
}
echo "<h2>Before</h2>";
neatPrint( $arr1 );
neatPrint( $arr2 );
echo "<hr/>";
function cloneArr( $old ) {
// I dunno how to properly clone
return $old;
}
function convertArr( $arr ) {
// Easy referencing without having to search through the arrays more than once for a matching id
$new_arr = array();
foreach( $arr as $array ) {
$new_arr[ $array['id'] ] = cloneArr( $array );
}
return $new_arr;
}
function merge( $arr1, $arr2 ) {
$convertedArr1 = convertArr( $arr1 );
$convertedArr2 = convertArr( $arr2 );
$arr = array();
// Based on the ordered array
foreach( $convertedArr1 as $array ) {
$id = $array['id'];
$tempArr = array();
neatPrint( $convertedArr1[ $id ] );
neatPrint( $convertedArr2[ $id ] );
foreach( $convertedArr1[ $id ] as $k => $v ) {
$tempArr[ $k ] = $v;
}
foreach( $convertedArr2[ $id ] as $k => $v ) {
$tempArr[ $k ] = $v;
}
array_push( $arr, $tempArr );
}
echo "<h2>Result</h2>";
return $arr;
}
echo "<h2>Loopthrough</h2>";
neatPrint( merge( $arr1, $arr2 ) );
?>
Let me know what you think :-)
if the element are in order try this code:
$arr = array();
for ($i=0; $i<count($first_array);$i++){
$arr['name'] = $first_array[$i]['name'];
$arr['id'] = $first_array[$i]['id'];
$arr['value_max'] = $first_array[$i]['value_max'];
$arr['difference_value'] = $first_array[$i]['value_max']-$second[$i['id']]['value_max'] ;
}

Categories