`Hi,
For example I've such array:
array:3 [
1 => array:1 [
"Home" => array:3 [
"Weight (kg)" => 4.0
"Length (cm)" => null
"Width (cm)" => null
]
]
2 => array:1 [
"Home" => array:3 [
"Weight (kg)" => 3.0
"Length (cm)" => 3.0
"Width (cm)" => null
]
]
3 => array:1 [
"Home" => array:3 [
"Weight (kg)" => 2.0
"Length (cm)" => 2.0
"Width (cm)" => null
]
]
]
Need to find a way to get biggest value & that's not a problem, I could find it easily, but how to find biggest value & return i.e. key number 1, cause it has the greatest value from all others.
Must be checked with locations i.e. Home, could be an array, need to find in group all maxes & return its parent id to mark as standard elements.
Someone could help with that?
Thanks anyway
I've found max value by method:
$max = null;
array_walk_recursive($values, function ($value) use (&$max) {
if ($max === null || $value > $max) $max = $value;
});
return $max;
But can't find a good way to return this element or it's key:
1 => array:1 [
"Home" => array:3 [
"Weight (kg)" => 4.0
"Length (cm)" => null
"Width (cm)" => null
]
]
The lambda you can hand over to the "array_walk" functions can accept two parameters, key and value. That should be the missing link you are looking for.
I slightly modified your approach that way:
<?php
$input = [
[
"Home" => [
"Weight (kg)" => 4.0,
"Length (cm)" => null,
"Width (cm)" => null
]
],
[
"Home" => [
"Weight (kg)" => 3.0,
"Length (cm)" => 3.0,
"Width (cm)" => null
],
"Office" => [
"Weight (kg)" => 3.0,
"Length (cm)" => 6.0,
"Width (cm)" => 2.0
]
],
[
"Home" => [
"Weight (kg)" => 2.0,
"Length (cm)" => 2.0,
"Width (cm)" => null
]
]
];
$max = null;
array_walk($input, function ($entry, $entryKey) use (&$max) {
array_walk($entry, function($loc, $locKey) use (&$max, $entryKey) {
$val = max($loc);
if ($max === null || $val > $max['val']) {
$max['val'] = $val;
$max['key'] = $entryKey;
$max['loc'] = $locKey;
}
});
});
printf("Maximum value '%.2f' of location '%s' is in element with key '%d'.", $max['val'], $max['loc'], $max['key']);
The output obviously is:
Maximum value '6.00' of location 'Office' is in element with key '1'.
An extended version of above code that finds and reports the maximum value for each of the given dimensions separately:
<?php
$input = [
1 => [
'Home' => [
'Weight (kg)' => 150.0,
'Length (cm)' => 120.0,
'Width (cm)' => 120.0,
'Height (cm)' => 60.0,
'Worth (€)' => 555,
],
],
2 => [
'Office' => [
'Weight (kg)' => 300.0,
'Length (cm)' => 120.0,
'Width (cm)' => 120.0,
'Height (cm)' => 60.0,
'Worth (€)' => 666,
],
],
3 => [
'Home' => [
'Weight (kg)' => 500.0,
'Length (cm)' => 120.0,
'Width (cm)' => 120.0,
'Height (cm)' => 100.0,
'Temperature (°C)' => 55,
],
'Office' => [
'Weight (kg)' => 1000.0,
'Length (cm)' => 120.0,
'Width (cm)' => 80.0,
'Height (cm)' => 220.0,
],
],
5 => [
'Condo' => [
'Weight (kg)' => 1250.0,
'Length (cm)' => 160.0,
'Width (cm)' => 120.0,
'Height (cm)' => 220.0,
],
],
6 => [
'Beach' => [
'Weight (kg)' => 1250.0,
'Length (cm)' => 260.0,
'Width (cm)' => 120.0,
'Height (cm)' => 220.0,
],
],
];
$max = [];
array_walk($input, function ($entry, $entryKey) use (&$max) {
array_walk($entry, function($loc, $locKey) use (&$max, $entryKey) {
array_walk($loc, function($val, $dimKey) use (&$max, $entryKey, $locKey) {
if (!array_key_exists($dimKey, $max) || $max[$dimKey]['val'] < $val) {
$max[$dimKey] = [
'key' => $entryKey,
'loc' => $locKey,
'val' => $val,
];
}
});
});
});
foreach ($max as $dim => $val) {
printf(
"Dimension '%s' has a maximum value '%.2f' with location '%s' is in element with key '%d'.\n",
$dim, $val['val'], $val['loc'], $val['key']
);
}
The output is:
Dimension 'Weight (kg)' has a maximum value '1250.00' with location 'Condo' is in element with key '5'.
Dimension 'Length (cm)' has a maximum value '260.00' with location 'Beach' is in element with key '6'.
Dimension 'Width (cm)' has a maximum value '120.00' with location 'Home' is in element with key '1'.
Dimension 'Height (cm)' has a maximum value '220.00' with location 'Office' is in element with key '3'.
Dimension 'Worth (€)' has a maximum value '666.00' with location 'Office' is in element with key '2'.
Dimension 'Temperature (°C)' has a maximum value '55.00' with location 'Home' is in element with key '3'.
You could do it this way:
<?php
$array = [
1 => [
"Home" => [
"Weight (kg)" => 4.0,
"Length (cm)" => null,
"Width (cm)" => null,
],
],
2 => [
"Home" => [
"Weight (kg)" => 3.0,
"Length (cm)" => 3.0,
"Width (cm)" => null,
],
],
3 => [
"Home" => [
"Weight (kg)" => 2.0,
"Length (cm)" => 2.0,
"Width (cm)" => null,
],
],
];
$biggestWeight = 0;
$biggestWeightKey = '';
foreach ($array as $key => $data) {
if ($data['Home']['Weight (kg)'] > $biggestWeight) {
$biggestWeight = $data['Home']['Weight (kg)'];
$biggestWeightKey = $key;
}
}
echo 'Biggest Weight is: ' . $biggestWeight . PHP_EOL;
echo 'Biggest Weight Key is: ' . $biggestWeightKey;
Output:
Biggest Weight is: 4
Biggest Weight Key is: 1
And if you want whole element:
echo '<pre>';
var_dump($array[$biggestWeightKey]);
Output:
array(1) {
["Home"]=>
array(3) {
["Weight (kg)"]=>
float(4)
["Length (cm)"]=>
NULL
["Width (cm)"]=>
NULL
}
}
Related
I have some cases where I need to do a split item for my shipment from items order.
the rule is max weight per 1 shipment is 5.
this is my items order :
$items = [
[
"sku" => "SKU-A",
"name" => "Product A",
"weight" => 7,
"dimension" => "20x30x10"
],
[
"sku" => "SKU-B",
"name" => "Product B",
"weight" => 4,
"dimension" => "10x10x20"
],
];
after doing split, i expect the result to this:
// will create new array
// limit weight per shipment max 5kg
$item1 = [
[
"sku" => "SKU-A",
"name" => "Product A",
"weight" => 5,
"dimension" => "20x30x10"
]
];
$item2 = [
[
"sku" => "SKU-A",
"name" => "Product A",
"weight" => 2,
"dimension" => "20x30x10"
], // this item from SKU-A where w => 7 - 5 = 2
[
"sku" => "SKU-B",
"name" => "Product B",
"weight" => 3,
"dimension" => "10x10x20"
],
];
$item3 = [
[
"sku" => "SKU-B",
"name" => "Product B",
"weight" => 1,
"dimension" => "10x10x20"
],// this item from SKU-B where w => 7 - 5 = 2
];
what's the posible way to do that? thank you.
#catLovers, I have made this code as desired... Please improvise/ optimise as necessary.
$items = [
[
"sku" => "SKU-A",
"name" => "Product A",
"weight" => 7,
"dimension" => "20x30x10"
],
[
"sku" => "SKU-B",
"name" => "Product B",
"weight" => 4,
"dimension" => "10x10x20"
],
];
$newItems = array();
for ($x = 0; $x <= count($items)-1; $x++) {
if ($items[$x]['weight'] > 5) {
$weight = $items[$x]['weight'];
$wt =5;
do {
$temp = array([
'sku' => $items[$x]['sku'],
'name' => $items[$x]['name'],
'weight' => $wt,
'dimension' => $items[$x]['dimension']
]);
array_push($newItems,$temp);
$weight=$weight-5;
if ($weight <=5){ $wt=$weight;}
} while ($weight <= 5);
echo "<pre>";
print_r($temp);
echo "</pre>";
}
else {
array_push($newItems,$items[$x]);
}
}
echo "<pre>";
print_r($newItems);
echo "</pre>";
Consider this array of objects in PHP:
array:2 [
0 => array:4 [
"Row_Id" => 256
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "452"
]
1 => array:4 [
"Row_Id" => 257
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "42"
]
2 => array:4 [
"Row_Id" => 258
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "428"
]
]
I want to add "callee_number:100" in every array so my output should look like these:
array:2 [
0 => array:5 [
"Row_Id" => 256
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "452"
"callee_number" => "100"
]
1 => array:5 [
"Row_Id" => 257
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "42"
"callee_number" => "100"
]
2 => array:5 [
"Row_Id" => 258
"Start_Date" => "2020-05-16"
"account_code" => ""
"caller_number" => "428"
"callee_number" => "100"
]
]
I have taken the above input array in $get variable. Now I am calling array_push to append callee_number to every array:
array_push($get,[
'callee_number':'100'
]);
Also tried using array_merge but callee_number is not getting appended. How can I achieve that ?
Given the following array:
$array = [
[
"Row_Id" => 256,
"Start_Date" => "2020-05-16",
"account_code" => "",
"caller_number" => "452",
],
[
"Row_Id" => 257,
"Start_Date" => "2020-05-16",
"account_code" => "",
"caller_number" => "42",
],
[
"Row_Id" => 258,
"Start_Date" => "2020-05-16",
"account_code" => "",
"caller_number" => "428",
],
];
Native PHP
$array = array_map(function ($item) { return $item + ['callee_number' => 100]; }, $array);
Using collections
$array = collect($array)->map(function ($item) { return $item + ['callee_number' => 100]; })->toArray();
Using PHP 7.4 shorthands
$array = array_map(fn($item) => $item + ['callee_number' => 100], $array);
// Or
$array = collect($array)->map(fn($item) => $item + ['callee_number' => 100])->toArray();
To add or modify an element in each sub-array you would do this:
foreach ($get as &$g) {
$g["callee_number"] = 100;
}
Or this:
for ($c = 0; $c < count($get); $c++) {
$get[$c]["callee_number"] = 100;
}
How to get particular nested array based on the given matched key using PHP built in function
Scenario
$id = 1035; // Searching ID
$a = [
'id'=> 291,
'children' => [
[
'id' => 1034,
'children' => [
[
'id' => 111,
'name' => 'ABC',
'figure' => '6 digits',
'children'=> []
],
[
'id' => 1035,
'lft' => 'LEFT',
'children' => [
[
'id' => 1036,
'children' => [
[
'id' => 222,
'someKey' => 'some value',
'children'=> []
]
]
],
[
'id' => 333,
'someKey' => 'some value',
'children'=> []
]
],
]
],
],
[
'id' => 1024,
'title' => 'ABC',
'children' => [
],
]
]
];
Please note, 'id' & 'children' keys are always be there. How to get the "children" of "1035" ID..?
Expected Output
[
[
'id' => 1036,
'children' => [
[
'id' => 222,
'someKey' => 'some value',
'children'=> []
]
],
],
[
'id' => 333,
'someKey' => 'some value',
'children'=> []
]
];
Tried
function getRecursiveCategoryIds($key, $categories = []){
$return = null;
try {
array_walk_recursive($categories, function($v, $k) use ($key, &$return){
if (null != $return) {
// Run loop to get the next immediate "children" key
if ($k == 'children') { // It's not matching anymore
$return = $v;
//return false;
throw new Exception;
}
} else if($v == $key) {
// Found
$return = $v;
}
});
} catch(Exception $e) {}
return $return;
}
$d = getRecursiveCategoryIds($id, $a);
echo '<pre>D: '; print_r($d); die;
I tried by the above code, but the "if ($k == 'children') {" is not matched any more..!
Any suggestions are welcome... (PHP's Built in function is most prefer!)
I was able to do this. Please check the comments in the code:
<?php
$id = 1035; // Searching ID
$myObj = array();
$a = [
'id'=> 291,
'children' => [
[
'id' => 1034,
'children' => [
[
'id' => 111,
'name' => 'ABC',
'figure' => '6 digits',
'children'=> []
],
[
'id' => 1035,
'lft' => 'LEFT',
'children' => [
[
'id' => 1036,
'children' => [
[
'id' => 222,
'someKey' => 'some value',
'children'=> []
]
]
],
[
'id' => 333,
'someKey' => 'some value',
'children'=> []
]
],
]
],
],
[
'id' => 1024,
'title' => 'ABC',
'children' => [
],
]
]
];
function findObject($id, $obj) {
global $myObj;
// This is an object.
if (isset($obj["id"])) {
echo "Checking {$obj["id"]}<br />";
// Check the id to what we need.
if ($obj["id"] == $id) {
// Yay! We found it. Return the object.
echo "Yay we found {$obj["id"]}<br />";
$myObj = $obj;
}
else {
echo "Checking children of {$obj["id"]}<br />";
// See if it has any children
if (isset($obj["children"]) && count($obj["children"]) > 0) {
echo "There are children for {$obj["id"]}<br />";
foreach ($obj["children"] as $child) {
findObject($id, $child);
}
}
}
}
}
findObject($id, $a);
print_r($myObj);
Output
Checking 291Checking children of 291There are children for 291Checking 1034Checking children of 1034There are children for 1034Checking 111Checking children of 111Checking 1035Yay we found 1035Need to find a way to break out!Checking 1024Checking children of 1024Found it!Array
(
[id] => 1035
[lft] => LEFT
[children] => Array
(
[0] => Array
(
[id] => 1036
[children] => Array
(
[0] => Array
(
[id] => 222
[someKey] => some value
[children] => Array
(
)
)
)
)
[1] => Array
(
[id] => 333
[someKey] => some value
[children] => Array
(
)
)
)
)
Demo:
https://ideone.com/UoKqrU
https://3v4l.org/rWkPq
You can use function inside other check :
$id=1035;
$a = [
'id'=> 291,
'children' => [
[
'id' => 1034,
'children' => [
[
'id' => 111,
'name' => 'ABC',
'figure' => '6 digits',
'children'=> []
],
[
'id' => 1035,
'lft' => 'LEFT',
'children' => [
[
'id' => 1036,
'children' => [
[
'id' => 222,
'someKey' => 'some value',
'children'=> []
]
]
],
[
'id' => 333,
'someKey' => 'some value',
'children'=> []
]
],
]
],
],
[
'id' => 1024,
'title' => 'ABC',
'children' => [
],
]
]
];
function nigsearch($arr,$id)
{
if(gettype($arr) == 'array')
foreach($arr as $key =>$list)
{
if(gettype($list) == 'array'){
if(isset($list['id']))
{
if($list['id'] ==$id)
print_r($list['children']);
}
nigsearch($list,$id);
}
}
}
foreach($a as $key)
{
nigsearch($key,$id);
}
Given array like this, I want to arrange data in a custom way.
array:5 [
0 => array:4 [
"message" => "Message number 1 for first conversation"
"is_seen" => 0
"user_id" => 2
"sent_time" => "2017-08-30 23:28:50"
]
1 => array:4 [
"message" => "Message number 2 for first conversation"
"is_seen" => 1
"user_id" => 1
"sent_time" => "2017-08-29 23:36:27"
]
2 => array:4 [
"message" => "Message number 3 for first conversation"
"is_seen" => 1
"user_id" => 1
"sent_time" => "2017-08-29 23:36:27"
]
3 => array:4 [
"message" => "Message number 4 for first conversation by second user"
"is_seen" => 1
"user_id" => 2
"sent_time" => "2017-08-29 23:36:27"
]
4 => array:4 [
"message" => "Message number 5 for first conversation by second user"
"is_seen" => 1
"user_id" => 2
"sent_time" => "2017-08-29 23:36:27"
]
]
What I want to do is to group messages that are sent by the same user so I get an array like this :
$data = [
"block" => [
[
"message" => "Message number 1 for first conversation",
"is_seen" => 0,
"user_id" => 2,
"sent_time" => "2017-08-30 23:28:50"
]
],
"block" => [
[
"message" => "Message number 2 for first conversation",
"is_seen" => 1,
"user_id" => 1,
"sent_time" => "2017-08-29 23:36:27"
],
[
"message" => "Message number 3 for first conversation",
"is_seen" => 1,
"user_id" => 1,
"sent_time" => "2017-08-29 23:36:27"
]
],
"block" => [
[
"message" => "Message number 4 for first conversation by second user",
"is_seen" => 1,
"user_id" => 2,
"sent_time" => "2017-08-29 23:36:27"
],
[
"message" => "Message number 5 for first conversation by second user",
"is_seen" => 1,
"user_id" => 2,
"sent_time" => "2017-08-29 23:36:27"
]
]
];
So basically, If next message user_id is same as previous message user_id add it to group array. If it is not, create new group array and so on. I do not want to group all user messages together since this structure is required for pagination in front-end.
You can do it like this
$new = array();
$prev = "";
$count =0;
foreach($arr as $key=> $value){
if($prev == $value["user_id"]){
$new[$count-1][] = $value;
}else {
$new[$count][] = $value;
$count++;
}$prev = $value["user_id"];
}
print_r($new);
Live demo : https://eval.in/854288
First of all you cannot have duplicate associative keys into the same array however, you group the blocks by some sequential number in the following way:
$group_num = 0;
$col = collect($data);
$col->groupBy(function ($item, $key) use (&$group_num, $col)
{
if (!isset($col[$key - 1]))
return "block_" . $group_num;
if ($item['user_id'] !== $col[$key - 1]['user_id'])
$group_num++;
return "block_" . $group_num;
})
->toArray();
The result it should be something like:
[
"block_0" => [
[
"message" => "Message number 1 for first conversation",
"is_seen" => 0,
"user_id" => 2,
"sent_time" => "2017-08-30 23:28:50",
],
],
"block_1" => [
[
"message" => "Message number 2 for first conversation",
"is_seen" => 1,
"user_id" => 1,
"sent_time" => "2017-08-29 23:36:27",
],
[
"message" => "Message number 3 for first conversation",
"is_seen" => 1,
"user_id" => 1,
"sent_time" => "2017-08-29 23:36:27",
],
],
"block_2" => [
[
"message" => "Message number 4 for first conversation by second user",
"is_seen" => 1,
"user_id" => 2,
"sent_time" => "2017-08-29 23:36:27",
],
[
"message" => "Message number 5 for first conversation by second user",
"is_seen" => 1,
"user_id" => 2,
"sent_time" => "2017-08-29 23:36:27",
],
],
]
I have a problem about bulk indexing.
I have created analysis and mapping, but this error is appear when I try to bulk indexing my data.
What is the problem with my code?
Elasticsearch_error
object(Elasticsearch\Common\Exceptions\UnexpectedValueException)[321]
protected 'message' => string '"id" is not a valid parameter. Allowed parameters are: "consistency", "refresh", "replication", "type", "client", "custom"' (length=122)
private 'string' (Exception) => string '' (length=0)
protected 'code' => int 0
protected 'file' => string 'D:\xampp\htdocs\lisento\vendor\elasticsearch\elasticsearch\src\Elasticsearch\Endpoints\AbstractEndpoint.php' (length=107)
protected 'line' => int 245
private 'trace' (Exception) =>
array (size=21)
0 =>
array (size=6)
'file' => string 'D:\xampp\htdocs\lisento\vendor\elasticsearch\elasticsearch\src\Elasticsearch\Endpoints\AbstractEndpoint.php' (length=107)
'line' => int 97
'function' => string 'checkUserParams' (length=15)
'class' => string 'Elasticsearch\Endpoints\AbstractEndpoint' (length=40)
'type' => string '->' (length=2)
'args' =>
array (size=1)
0 =>
array (size=1)
'id' => string '1234567890' (length=10)
AbstractEndpoint.php
private function checkUserParams($params)
{
if (isset($params) !== true) {
return; //no params, just return.
}
$whitelist = array_merge($this->getParamWhitelist(), array('client', 'custom'));
foreach ($params as $key => $value) {
if (array_search($key, $whitelist) === false) {
throw new UnexpectedValueException(sprintf(
'"%s" is not a valid parameter. Allowed parameters are: "%s"',
$key,
implode('", "', $whitelist)
));
}
}
}
My_mapping
[
"mappings" => [
"twitter" => [
"properties" => [
"tweet_id" => [ "type" => "long" ],
"tweet_text" => [
"type" => "string",
"fields" => [
"raw" => [ "type" => "string", "index" => "no" ],
"text" => [ "type" => "string", "analyzer" => "tweet_text_autocomp_analyzer" ],
"std" => [ "type" => "string", "analyzer" => "tweet_text_std_analyzer" ]
],
],
"tweet_date" => ["type" => "date","format" => "Y-M-d H:m:s" ],
"favorited_count" => [ "type" => "integer" ],
"retweet_count" => [ "type" => "integer" ],
"place" => [ "type" => "string" ],
"url" => [ "type" => "string" ],
"hashtags" => [
"type" => "nested",
"fields" => [
"hashtag" => [ "type" => "string" ]
],
],
"campaign_id" => [ "type" => "long" ],
"user_id" => [ "type" => "long" ],
"screen_name" => [ "type" => "string" ]
]
]
]
]
My_data
{
"user_id": 117093939,
"screen_name": "",
"campaign_id": "1234567890",
"tweet_id": 609287367120150000,
"tweet_text": "Oberyn's scattered skull #GameOfThronesFood",
"tweet_date": "2015-06-12 16:13:22",
"favorited_count": 0,
"retweet_count": 0,
"url": ""
},
{
"user_id": 491504312,
"screen_name": "",
"campaign_id": "1234567890",
"tweet_id": 609287361751610000,
"tweet_text": "RT #alex_backes: Buffalo Wildlings #GameOfThronesFood #midnight",
"tweet_date": "2015-06-12 16:13:21",
"favorited_count": 0,
"retweet_count": 43,
"url": ""
},
{
"user_id": 745355136,
"screen_name": "",
"campaign_id": "1234567890",
"tweet_id": 609287345951610000,
"tweet_text": "RT #CMPunk: Jon snow cones! #midnight #GameOfThronesFood",
"tweet_date": "2015-06-12 16:13:17",
"favorited_count": 0,
"retweet_count": 203,
"url": ""
}
}
My_bulk_code
for ($j = 0; $j <= $i; $j++) {
$params ['body'][] = array(
'index' => array(
'index' => $appconfig['ES_INDEX'],
'type' => $index["type"],
'_id' => $j,
'body' => $index["docs"]
),
);
// Every 1000 documents stop and send the bulk request
if ($j % 1000) {
$responses = $client->bulk($params);
// erase the old bulk request
$params = array();
// unset the bulk response when you are done to save memory
unset($responses);
}
}
here is the answer.
https://github.com/elastic/elasticsearch-php/issues/247
it works fine.
You must check that the value of the param is not empty. When the value is empty, you will get a malformed data that will cause this error.