My collection:
($usersWithCommission) Illuminate\Support\Collection {#2625
#items: array:2 [
0 => array:3 [
"userId" => 1
"name" => "Sim Aufderhar"
"net_commission" => null
]
1 => array:3 [
"userId" => 2
"name" => "Carolyn Lang III"
"net_commission" => null
]
]
}
I would like modify the net_commission property, but I can not:
foreach ($soldProperties as $property) {
if (!$property->buyer_user_id && !$property->seller_transferring_user_id) {
$usersWithCommission->where('userId', $property->user_id)->first()['net_commission'] += $property->net_commission_of_sold;
}
}
How I can?
Thanks your answers.
Collections provide a method map which allows you to iterate your collection and add/modify fields.
function modify_net_commision($var) {
return YOUR_LOGIC_HERE;
}
$collection = [
[ "userId" => 1, "name" => "Sim Aufderhar", "net_commission" => null ],
[ "userId" => 2, "name" => "Carolyn Lang III", "net_commission" => null ],
];
$external_var = 'I will be used on modify_net_commision function';
$new_collection = collect($collection)->map(function ($arr) use ($external_var) {
$arr['net_commission'] = modify_net_commision($external_var);
return $arr;
})
If you want to remove some fields from your collection, use reject method.
Doc: https://laravel.com/docs/5.8/collections
Hope it helps you.
Have a great day.
public function test()
{
$collection = [
[ "userId" => 1, "name" => "Sim Aufderhar", "net_commission" => null ],
[ "userId" => 2, "name" => "Carolyn Lang III", "net_commission" => null ],
];
$data= collect($collection)->map(function($collection, $key) {
$collect = (object)$collection;
return [
'userId' => $collect->userId,
'name' => $collect->name,
'net_commission' => $this->modify_commision($key)
];
});
dd($data);
}
public function modify_commision($key) {
$property = [
['userId' => 1 ,'net_commission_of_sold' => 30],
['user_id' => 2,'net_commission_of_sold' => 40]
];
return $property[$key]['net_commission_of_sold'];
}
***Hope it helps you***
Related
I have nth level of nested array with string naming key , I want to convert that in indexing key only for array of item key.
i tried it to convert but that conversation only possible for limited level of nested array rather than nth level .
Input array:
$input_array= [
"NOCPL-All -working" => [
"name" => "NOCPL-All -working",
"item" => [
"apis for web" => [
"name" => "apis for web",
"item" => [
"0" => [
"name" => "update user branch maps"
]
]
],
"update user web" => [
"name" => "update user web",
"item" => [
"0" => [
"name" => "update user"
],
"1" => [
"name" => "add user"
]
]
]
]
]
];
I tried below code to convert indexing of 'item' nested array for limited level
function cleanArrayKeys($arr) {
foreach($arr as $k=>$arr1) {
if(isset($arr[$k]['item'])) {
$arr[$k]['item'] = array_values($arr[$k]['item']);
foreach($arr[$k]['item'] as $k1=>$arr2) {
if(isset($arr[$k]['item'][$k1]['item'])) {
$arr[$k]['item'][$k1]['item'] = array_values($arr[$k]['item'][$k1]['item']);
foreach($arr[$k]['item'][$k1]['item'] as $k3=>$arr3) {
if(isset($arr[$k]['item'][$k1]['item'][$k3]['item'])) {
$arr[$k]['item'][$k1]['item'][$k3]['item'] = array_values($arr[$k]['item'][$k1]['item'][$k3]['item']);
foreach($arr[$k]['item'][$k1]['item'][$k3]['item'] as $k4=>$arr4) {
if(isset($arr[$k]['item'][$k1]['item'][$k3]['item'][$k4]['item'])) {
$arr[$k]['item'][$k1]['item'][$k3]['item'][$k4]['item'] = array_values($arr[$k]['item'][$k1]['item'][$k3]['item'][$k4]['item']);
foreach($arr[$k]['item'][$k1]['item'][$k3]['item'][$k4]['item'] as $k5=>$arr5) {
if(isset($arr[$k]['item'][$k1]['item'][$k3]['item'][$k4]['item'][$k5]['item'])) {
$arr[$k]['item'][$k1]['item'][$k3]['item'][$k4]['item'][$k5]['item'] = array_values($arr[$k]['item'][$k1]['item'][$k3]['item'][$k4]['item'][$k5]['item']);
}
}
}
}
}
}
}
}
}
}
return $arr;
}
print_r(cleanArrayKeys($input_array));
?>
Expected Output :
[
"NOCPL-All -working" => [
"name" => "NOCPL-All -working",
"item" => [
"0" => [
"name" => "apis for web",
"item" => [
"0" => [
"name" => "update user branch maps"
],
"1" => [
"name" => "add user branch maps"
]
]
],
"1" => [
"name" => "update user web",
"item" => [
"0" => [
"name" => "update user"
]
]
]
]
]
];
Try using a recursion:
function aValues(&$arr) {
if (array_key_exists('item', $arr)) {
$arr['item'] = array_values($arr['item']);
}
foreach ($arr['item'] as &$el) {
if (array_key_exists('item', $el)) {
aValues($el);
}
}
}
aValues($input_array);
print_r($input_array);
I am trying to loop through an array of block components, that each can have n number of nested components (profile or avatar).
Now, what I want to do is to show these blocks x number of times, where x is the number of data from a payload array:
$payload['users'] = [
['name' => 'Oliver'],
['name' => 'John']
];
So since the above payload users length is 2, this should be rendered:
- block #1
-- profile
-- avatar
- block #2
-- profile
-- avatar
I am trying to render the above the same way by using a nested foreach loop. See the below code:
$payload['users'] = [
['name' => 'Oliver'],
['name' => 'John']
];
$schema = [
"id" => 1,
"name" => "Users",
"components" => [
[
"key" => "0",
"name" => "block",
"components" => [
[
"key" => "1",
"name" => "profile"
],
[
"key" => "2",
"name" => "avatar"
]
],
]
],
];
$toPush = [];
foreach ($schema['components'] as $key => $value) {
foreach ($value['components'] as $no => $component) {
$iterator = $payload['users'];
for ($x = 0; $x < count($iterator); $x ++) {
$copy = $component;
$copy['item'] = $iterator[$x];
$copy['key'] = $copy['key'] . '-' . $x;
$toPush[] = $copy;
}
$schema['components'][$key]['components'] = $toPush;
}
}
print_r($toPush);
The problem is that the above prints it out like this:
- block #1
-- profile
-- profile
- block #2
-- avatar
-- avatar
I have created an 3v4l of this, which can be found here.
How can I achieve my desired scenario?
For reference I am using the Laravel framework.
Desired output
Also available as an 3v4l here.
[
"components" => [
[
"key" => "1",
"name" => "profile",
"item" => [
"name" => "Oliver"
]
],
[
"key" => "2",
"name" => "avatar",
"item" => [
"name" => "Oliver"
]
],
[
"key" => "3",
"name" => "profile",
"item" => [
"name" => "John"
]
],
[
"key" => "4",
"name" => "avatar",
"item" => [
"name" => "John"
]
]
],
];
This logic may be of some help to you.
$toPush = [];
$count = 0;
foreach ($schema['components'] as $value) {
foreach ($value['components'] as $key => $component) {
foreach ($payload['users'] as $idx => $user) {
$toPush['components'][$count]['key'] = $count;
$toPush['components'][$count]['name'] = $value['components'][$idx]['name'];
$toPush['components'][$count]['item'] = $payload['users'][$key];
$count++;
}
}
}
demo
I'd like to sort the following associative array:
$tree = [
"id" => 245974,
"children" => [
[
"id" => 111
],
[
"id" => 245982,
"children" => [
[
"id" => 246093,
"children" => [
[
"id" => 225892
],
[
"id" => 225893
],
[
"id" => 225902
]
]
]
]
]
]
];
Desired sort order after the "search value" of id => 225902:
[
"id" => 245974,
"children" => [
[
"id" => 245982, // <-- this is moved up
"children" => [
[
"id" => 246093,
"children" => [
[
"id" => 225902 // <-- this is moved up
],
[
"id" => 225892
],
[
"id" => 225893
]
]
]
]
],
[
"id" => 111
]
]
];
What I've tried:
<?php
$category_id = 225902;
function custom_sort(&$a, &$b) {
global $category_id;
if ($a['id'] === $category_id) {
return -1;
}
if ($b['id'] === $category_id) {
return 1;
}
if (array_key_exists('children', $a)) {
if (usort($a['children'], "custom_sort")) {
return -1;
}
}
if (array_key_exists('children', $b)) {
if (usort($b['children'], "custom_sort")) {
return 1;
}
}
return 0;
}
function reorder_tree($tree) {
usort($tree['children'], "custom_sort");
return $tree;
}
echo "<pre>";
var_dump(reorder_tree($tree));
echo "</pre>";
However, that returns:
[
"id" => 245974,
"children" => [
[
"id" => 245982, // <- this is moved up
"children" => [
[
"id" => 246093,
"children" => [
[
"id" => 225892
],
[
"id" => 225893
],
[
"id" => 225902 // <- this is *not* moved up
]
]
]
]
],
[
"id" => 111
],
]
];
How would I be able to also sort the children arrays?
Great attempt and very much on the right track. The problem with recursion in the comparator is that usort will not call the comparator function when the array length is 1, so whether or not you explore the whole tree is at the whim of usort. This will abandon id => 245982's branch of the tree.
The solution is to avoid recursing in the usort's comparator function directly. Rather, use a regular recursive function that calls usort as needed, namely, the current array or a child array contains the target id. I use a separate array to keep track of which elements should be moved forward, but you can break out of the loop and splice/unshift a single element to the front if you prefer.
We can also make $category_id a parameter to the function.
Here's one approach:
function reorder_tree_r(&$children, $target) {
$order = [];
$should_sort = false;
foreach ($children as $i => &$child) {
$order[$i] = false;
if (array_key_exists("children", $child) &&
reorder_tree_r($child["children"], $target) ||
$child["id"] === $target) {
$order[$i] = true;
$should_sort = true;
}
}
if ($should_sort) {
$priority = [];
$non_priority = [];
for ($i = 0; $i < count($children); $i++) {
if ($order[$i]) {
$priority[]= $children[$i];
}
else {
$non_priority[]= $children[$i];
}
}
$children = array_merge($priority, $non_priority);
}
return $should_sort;
}
function reorder_tree($tree, $target) {
if (!$tree || !array_key_exists("children", $tree)) {
return $tree;
}
reorder_tree_r($tree["children"], $target);
return $tree;
}
var_export(reorder_tree($tree, 225902));
Output:
array (
'id' => 245974,
'children' =>
array (
0 =>
array (
'id' => 245982,
'children' =>
array (
0 =>
array (
'id' => 246093,
'children' =>
array (
0 =>
array (
'id' => 225902,
),
1 =>
array (
'id' => 225892,
),
2 =>
array (
'id' => 225893,
),
),
),
),
),
1 =>
array (
'id' => 111,
),
),
I am having three arrays
topicsSelected
relavantGroups
topicAssingned
$topicsSelected = [ "T-100","T-600"];
$relavantGroups = [
[ "id" => "G-001","name" => "3 A","active" => false ],
["id" => "G-002","name" => "3 B","active" => false]
];
$topicAssingned = [
"G-001" => [
"groupID" => "G-001",
"groupName" => "3 A",
"topics" => [
"T-100" => [
"topicID" => "T-100"
],
"T-200" => [
"topicID" => "T-200"
]
]
],
"G-002" => [
"groupID" => "G-002",
"groupName" => "3 B",
"topics" => [
"T-400" => [
"topicID" => "T-400"
],
"T-500" => [
"topicID" => "T-500"
]
]
],
];
$topicsSelected array values at least one value should present $topicAssingned means based on groupID, i have to push one value to $relavantGroups like disable : D suppose value not present means disable : A
Expected output:
[
"id" => "G-001",
"name" => "3 A",
"active" => false,
"disable" => "D"
],
[
"id" => "G-002",
"name" => "3 B",
"active" => false,
"disable" => "A"
]
<?php
$topicsSelected = [ "T-100","T-600"];
$relavantGroups = [
[ "id" => "G-001","name" => "3 A","active" => false ],
["id" => "G-002","name" => "3 B","active" => false]
];
$topicAssigned = [
"G-001" => [
"groupID" => "G-001",
"groupName" => "3 A",
"topics" => [
"T-100" => [
"topicID" => "T-100"
],
"T-200" => [
"topicID" => "T-200"
]
]
],
"G-002" => [
"groupID" => "G-002",
"groupName" => "3 B",
"topics" => [
"T-400" => [
"topicID" => "T-400"
],
"T-500" => [
"topicID" => "T-500"
]
]
],
];
$topic_selected_map = [];
foreach($topicsSelected as $each_topic){
$topic_selected_map[$each_topic] = true;
}
$relevant_group_map = [];
foreach($relavantGroups as $each_group){
$relevant_group_map[$each_group['id']] = $each_group;
}
$result = [];
foreach($topicAssigned as $each_assigned_topic){
if(!isset($relevant_group_map[$each_assigned_topic['groupID']])) continue;
$topics_not_found = true;
foreach($each_assigned_topic['topics'] as $each_topic => $topic_details){
if(isset($topic_selected_map[$each_topic])){
$topics_not_found = false;
break;
}
}
$result[] = [
'id' => $each_assigned_topic['groupID'],
'name' => $each_assigned_topic['groupName'],
'active' => $relevant_group_map[$each_assigned_topic['groupID']]['active'],
'disable' => ($topics_not_found === true ? 'A' : 'D')
];
}
print_r($result);
Output:
Array
(
[0] => Array
(
[id] => G-001
[name] => 3 A
[active] => false
[disable] => D
)
[1] => Array
(
[id] => G-002
[name] => 3 B
[active] => false
[disable] => A
)
)
First, make a map(associative array) of values of $topicsSelected. Same goes for $relavantGroups. This is to make the check more efficient. See more on Hash Table.
Now, iterate over $topicAssigned and then iterate over each group's topics inside it. Now, check if a topic exists inside $topicsSelected using a simple isset function. If yes, we disable them, else we don't.
It's not very clear what you are asking and the code is a bit weird but I'll give it a try.
First fix your array declaration - you should use => and not :;
You have to Iterate over the $relavantGroups and for each element iterate the $topicAssingned array. Then perform a simple comparison to see if the group Id is present and you are done!
Here is my solution (quick and dirty): You can see it here
foreach ($relavantGroups as &$g) {
$found = false;
foreach ($topicAssingned as $key => $assigned) {
if ($key === $g["id"] && is_array($assigned["topics"])) {
foreach ($assigned["topics"] as $topic) {
if (in_array($topic["topicID"], $topicsSelected)) {
$found = true;
break;
}
}
}
}
$g["disable"] = $found ? "D" : "A";
}
var_dump($relavantGroups);
Updated the solution - note that I'm using in_array() to determine if the topicID is present. That mean that any value that is in the $topicsSelected array will affect the result.
Hope I helped.
This will output (based one your example):
array(2) {
[0]=> array(4) {
["id"]=> string(5) "G-001"
["name"]=> string(3) "3 A"
["active"]=> bool(false)
["disable"]=> string(1) "D"
}
[1]=> array(4) {
["id"]=> string(5) "G-002"
["name"]=> string(3) "3 B"
["active"]=> bool(false)
["disable"]=> string(1) "A"
}
}
I have an array that looks like this:
RecursiveArrayIterator {#605 ▼
+"xs:schema": array:2 [▼
"value" => array:1 [▼
"xs:element" => array:2 [▼
"value" => array:1 [▼
"xs:complexType" => array:2 [▼
"value" => array:2 [▼
"xs:sequence" => array:2 [▼
"value" => array:1 [▼
"xs:element" => array:3 [▼
0 => array:2 [▼
"value" => array:1 [▼
"xs:simpleType" => array:2 [▼
"value" => array:1 [▼
"xs:restriction" => array:2 [▼
"value" => array:1 [▼
"xs:maxLength" => array:1 [▼
"attributes" => array:1 [▼
"value" => "40"
]
]
]
"attributes" => array:1 [▶]
]
]
"attributes" => []
]
]
"attributes" => array:1 [▼
"name" => "title"
]
]
1 => array:2 [▶]
2 => array:2 [▶]
]
]
"attributes" => []
]
"xs:attribute" => array:2 [▶]
]
"attributes" => []
]
]
"attributes" => array:1 [▼
"name" => "book"
]
]
]
"attributes" => []
]
}
I need to access the xs:maxLength attribute, so in order to that that, I'm using the following method:
private function findRestrictions(array $haystack, $needle)
{
$iterator = new \RecursiveArrayIterator($haystack);
$recursive = new \RecursiveIteratorIterator(
$iterator,
\RecursiveIteratorIterator::SELF_FIRST
);
foreach ($recursive as $key => $value)
{
if ($key === $needle)
{
return (int)$value['attributes']['value'];
}
}
}
$maxLength = findRestrictions($array, 'xs:maxLength');
So that gives me back 40, just like expected. Anyway, my issue is that I need to know to which element this limit belongs to, which is mentioned in xs:element[0]['attributes']['name'] and I'm uncertain on how to reach there to grab the information I need, based on the match for xs:maxLength.
Well I have programmed a pretty good solution I think, this time it is tested.
My sample array:
$array = [
"we" =>
["are" => [
"lorem" => [
"gone" => "away",
"my" => "friend"
],
"never" => "abcd",
"any" => [
"btc" => "abc",
"help" => [
"mqf" => "bmx"
]
]
]
],
"fancy" => [
"lorem" => [
"gone" => "away",
"my" => "friend"
],
"never" => "abcd",
"any" => [
"btc" => "abc",
"help" => [
"mqf" => "bmx",
"abc" => 13
]
]
],
"beer" => "bar",
"helpful" => [
"meta" => "column",
"gamma" => [
"lorem" => [
"gone" => "mad",
"my" => "drink"
],
"never" => "abcd",
"any" => [
"btc" => "abc",
"help" => [
"mqf" => "bmx",
"abc" => "alot"
]
]
]
],
"elements" => [
0 => 88,
1 => 99
]
];
My solution:
function array_find_value_return_parent($array,$needle,$parentkey) {
$iterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array),
RecursiveIteratorIterator::SELF_FIRST);
foreach($iterator as $key => $value) {
if($value === $needle) {
for ($i = $iterator->getDepth() - 1; $i >= 0; $i--) {
if($iterator->getSubIterator($i)->key() === $parentkey) {
return $iterator->getSubIterator($i)->current();
}
}
}
}
}
function array_find_key_return_value($array,$findkey) {
$iterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array),
RecursiveIteratorIterator::SELF_FIRST);
foreach($iterator as $key => $value) {
if($findkey === $key) {
return $iterator->current();
}
}
}
My test:
$findvalue = "alot";
$findparentkey = "gamma";
$findreturnkey = "gone";
echo array_find_key_return_value(array_find_value_return_parent($array,$findvalue,$findparentkey),$findreturnkey);
Output: mad
For your case it means that you might do the following:
$findvalue = "40";
$findparentkey = "xs:element";
$findreturnkey = "name";
echo array_find_key_return_value(array_find_value_return_parent($array,$findvalue,$findparentkey),$findreturnkey);
Expected output: title
Right?
I do not know your original data structure, so I just converted your data to a PHP array. You can use $aks = new ArrayKeySearcher($data, 'xs:maxLength'); to find the key you want. And you can make the search more complex to satisfy your requirement.
However, if you are using something like XML, it is highly recommended to use XML-based solutions, like XPath query (eg: http://php.net/manual/en/domxpath.query.php, http://php.net/manual/en/simplexmlelement.xpath.php). These methods are easier to use, faster and more accurate.
<?php
$data = [
"xs:schema"=> [
"value" => [
"xs:element" => [
"value" => [
"xs:complexType" => [
"value" => [
"xs:sequence" => [
"value" => [
"xs:element" => [
0 => [
"value" => [
"xs:simpleType" => [
"value" => [
"xs:restriction" => [
"value" => [
"xs:maxLength" => [
"attributes" => [
"value" => "40"
]
]
],
"attributes" => []
]
],
"attributes" => []
]
],
"attributes" => [
"name" => "title"
]
],
1 => [],
2 => [],
]
],
"attributes" => []
],
"xs:attribute" => []
],
"attributes" => []
]
],
"attributes" => [
"name" => "book"
]
]
],
"attributes" => []
]
];
class ArrayKeySearcher
{
public $data;
public $path;
public $value;
public function __construct($data, $key)
{
$this->data = $data;
$this->findKeyPath($data, $key);
}
private function findKeyPath($data, $key)
{
foreach ($data as $k => $v) {
$this->path[] = $k;
if ($key === $k) {
$this->value = $v;
return;
}
$this->findKeyPath($v, $key);
if (!is_null($this->value))
return;
array_pop($this->path);
}
}
public function arrayReverseSearch($a, $k, $pos = null)
{
$count = count($a);
$i = ($pos === null) ? ($count - 1) : $pos;
for(; $i >= 0; $i--) {
if($a[$i] === $k)
return $i;
}
return $i;
}
public function getValueByPath($path)
{
$v = $this->data;
foreach($path as $k) {
if(isset($v[$k]))
$v = $v[$k];
}
return $v;
}
}
$aks = new ArrayKeySearcher($data, 'xs:maxLength');
echo 'path: ' . json_encode($aks->path) . PHP_EOL;
echo 'value: ' . json_encode($aks->value) . PHP_EOL;
$p = $aks->path;
$pos = $aks->arrayReverseSearch($p, 'xs:simpleType');
$pos = $aks->arrayReverseSearch($p, 'value', $pos);
$p = array_slice($p, 0, $pos);
$parent = $aks->getValueByPath($p);
echo 'parent path: ' . json_encode($p) . PHP_EOL;
echo 'parent attributes: ' . json_encode($parent['attributes']) . PHP_EOL;
Output:
path: ["xs:schema","value","xs:element","value","xs:complexType","value","xs:sequence","value","xs:element",0,"value","xs:simpleType","value","xs:restriction","value","xs:maxLength"]
value: {"attributes":{"value":"40"}}
parent path: ["xs:schema","value","xs:element","value","xs:complexType","value","xs:sequence","value","xs:element",0]
parent attributes: {"name":"title"}