How to Group array then iterate - arrays

I have trouble with my project.
First, I have a data like this : https://jsoneditoronline.org/?id=c6d15407962e4d1b986435ad3c283b4e
Then I group the data using this:
private function _group_by($array, $key) {
$new = [];
foreach ($array as $value) {
$new[$value[$key]][] = $value;
}
return $new;
}
$key = 'water_id'
After that the following result is like this: https://jsoneditoronline.org/?id=72991d45938c49a38900703feb3a60e7
From result above I cant iterate the data (I want to iterate since beginning). So, I want to able iterate the data, it is something wrong with my group by array function ? If you understand what I want, please help.

You can use collections to manipulate arrays or Traversable objects.
Grouping in CakePHP's Collection
use Cake\Collection\Collection;
private function _group_by($array, $key) {
$collection = new Collection($array);
return $collection->groupBy('water_id')->toArray();
}

You tagged this as being a Laravel App, right? Check out Collections: https://laravel.com/docs/5.6/collections.
$result = null;
collect($array)->groupBy($keyName)->each(function ($group, $key) use (&$result) {
foreach ($group as $element => $index) {
//Do something to $result.
}
});
Depending on your circumstances, map or transform might be more appropriate than each.

Related

Convert Laravel array collection to array

I was updating may images array which is found in following format:
[
"d756d3d2b9dac72449a6a6926534558a.jpg",
"b607aa5b2fd58dd860bfb55619389982.jpg",
"f937c8fddbe66ab03c563f16d5cfa50c.jpg"
]
So to delete a single image d756d3d2b9dac72449a6a6926534558a.jpg from this array column I used the filter method like below:
$collection = collect($imageColumn)->filter(
function ($valueTobeDeleted) use ($array) {
return !in_array($valueTobeDeleted, $array);
}
);
so after filter I wan to update my database with the new collection, but the new collection is in a map format like below
array:2 [
1 => "b607aa5b2fd58dd860bfb55619389982.jpg"
2 => "f937c8fddbe66ab03c563f16d5cfa50c.jpg"
]
the problem is i don't need those keys 1, and 2 my expectation was
array:2 [
"b607aa5b2fd58dd860bfb55619389982.jpg"
"f937c8fddbe66ab03c563f16d5cfa50c.jpg"
]
How can I achieve my expectation? How can I convert them to array?
Because you are using a Collection, you can do ->values() at the end so you convert all keys into integer keys and beginning from 0, like a normal non-associative array:
$collection = collect($imageColumn)->filter(
function ($valueTobeDeleted) use ($array) {
return !in_array($valueTobeDeleted, $array);
}
)
->values();
In order to re-index an array, you can use the array_values PHP function:
$arr = array_values($arr);
This will fix the keys.
Use array_values to get a an array of that associatve array.
$collection = collect($imageColumn)->
$filtered = filter(function ($valueTobeDeleted) use ($array) {
return !in_array($valueTobeDeleted, $array);
});
$filtered = array_values($filtered);

Laravel Collection - Return Array of Objects

So I am trying to return an array of objects with my Laravel collection using the following code:
/**
* View a user's chat rooms.
*
* return \Illuminate\Http\Response|\Laravel\Lumen\Http\ResponseFactory\
*/
public function viewChatRooms()
{
$user = Auth::user(); // #var User $user
$username = $user->username;
$rooms = Room::with('messages')->get()
->filter(function ($val) use ($username){
foreach ($val->users as $user) {
if($user === $username){
return $val;
}
}
});
return response(['rooms' => $rooms]);
}
Instead of returning an array of objects, the response returns the following:
{
"rooms": {
"0": {...},
"3": {...}
}
}
This is the desired result:
{
"rooms": [
{...},
{...}
]
}
Kind of stumped by this, could some one guide me in the right direction?
You Can use array_value function of PHP when returning response like this:
return response()->json([
'rooms' => array_values($rooms->toArray())
]);
Laravel Collection Methods for Getting only values of Collection
https://laravel.com/docs/5.8/collections#method-values
So
return response()->json([
'rooms' => $rooms->values()->toArray()
]);
The issue was that I didn't rebase the array since it skipped a few keys. I fixed it by simply using array_values() like so:
$rooms = Room::with('messages')->get()
->filter(function ($val) use ($username){
foreach ($val->users as $user) {
if($user === $username){
return $val;
}
}
});
return response(['rooms' => array_values($rooms->toArray())]);
I think that you will find that doing this within your DB query will be better performance wise.
Something like this:
$rooms = Room::whereHas('users', function(user) use ($username) {
return $user == $username
})
->with('messages')
->get();
To return an array of objects, you can use the all method.
Instead of returning a collection of objects, it returns an array of objects.
For example, User::all(); returns an Eloquent collection which is structured like so:
[
{App\User},
{App\User},
{App\User}
]
Whereas, the other answers suggest using ->toArray() which returns an array of arrays, not an array of objects, e.g.:
[
[
'id' => 123,
'name' => 'example'
...
],
[
...
]
]

Powershell: How to dynamically update a nested JSON array?

What I'm trying to do is take any well-formed JSON file/object and search for a path inside it. If the path isn't found, move on. If it is found, update the value. Once updated, save the updated JSON to the original file.
The catch to this, is the well-formed JSON structure is not known ahead of time. It's possible I might be searching hundreds of .json files on a disk, so the files that don't match any of my search terms can just be ignored.
I'm struggling to wrap my head around how to solve this problem. Most of the examples out there don't have a JSON object with an array for one of the key values, or they don't access the properties dynamically when an array is involved.
This link: Powershell: How to Update/Replace data and values in Json and XML Object shows a (sort of)"real" JSON structure, but the accepted answer relies on knowing what the JSON structure is (the OP didn't ask for help with dynamic pathing).
This link: Set Value of Nested Object Property by Name in PowerShell has something very close, although when an array is in the mix, it doesn't work properly when setting.
Here's some example JSON to use with this problem, though again, the structure is not known before the script runs. I'm looping over a list of files on disk, and executing for each file.
$JSON = ConvertFrom-Json '{
"key1":"key 1 value",
"options":{
"outDir":"./app-dir",
"lib":[
"someLibrary",
"anotherLibrary"
],
"someObjects":[
{
"first":"I am first"
},
{
"second":"I am second"
}
]
}
}'
The string to search this json might look like the following:
$SearchString = 'options.someObjects.first'
Or perhaps, something non-existent like:
$SearchString = 'options.someObjects.foo'
Using the recursive function GetValue from the 2nd article works beautifully for getting (and much more elegant than what I was doing):
function GetValue($object, $key)
{
$p1,$p2 = $key.Split(".")
if($p2) { return GetValue -object $object.$p1 -key $p2 }
else { return $object.$p1 }
}
However, the function SetValue does not work with an array. It returns an error stating "The property 'first' can not be found on this object."
function SetValue($object, $key, $Value)
{
$p1,$p2 = $key.Split(".")
if($p2) { SetValue -object $object.$p1 -key $p2 -Value $Value }
else { $object.$p1 = $Value }
}
I am aware this is because $JSON.options.someObjects is an array, therefore to access the object with the "first" key, the path would be:
$JSON.options.someObjects[0].first
That's the problem I'm having. How do I dynamically iterate over all objects once it reaches a part of the path that needs iterating? That part of the path could be anywhere, or more levels down, etc...
It's strange that powershell will allow you to dynamically iterate through an array when getting the value, but not when trying to set it.
Here's a complete example which demonstrates the entire issue:
#Create JSON:
$JSON = ConvertFrom-Json '{
"key1":"key 1 value",
"options":{
"outDir":"./app-dir",
"lib":[
"someLibrary",
"anotherLibrary"
],
"someObjects":[
{
"first":"I am first"
},
{
"second":"I am second"
}
]
}
}'
$SearchPath = 'options.someObjects.first'
$NewValue = 'I am a new value'
function GetValue($object, $key)
{
$p1,$p2 = $key.Split(".")
if($p2) { GetValue -object $object.$p1 -key $p2 }
else { return $object.$p1 }
}
function SetValue($object, $key, $Value)
{
$p1,$p2 = $key.Split(".")
if($p2) { SetValue -object $object.$p1 -key $p2 -Value $Value }
else { return $object.$p1 = $Value }
}
GetValue -object $JSON -key $SearchPath
SetValue -object $JSON -key $SearchPath -Value $NewValue
I've been searching all kinds of different terms trying to arrive at a good solution for this problem, but so far, no luck. I'm fairly certain I'm not the 1st person to want to do this sort of thing, apologies if I missed the answer somewhere.
There are two issues with your SetValue script:
Returning the object
An Object ([Object]) vs an object array
([Object[]])
Return
You can't return an assignment like return $object.$p1 = $Value. The assignment itself returns nothing with will result in returning a $Null to caller.
Besides, if you return the $Object for each recursive call, you will need to void ($Null = SetValue -object...) it by each parent caller so that it is only returned by the top caller. but keep in mind that you are actually poking the $NewValue in the original ($JSON) object!. If you don't want that, you will need to figure out the top caller and only copy the $Object at the top level before the recursive call.
Object array
You not just dealing with properties containing single objects but each property might potentially contain a collection objects. In fact, the leaf property SomeObject is an example of this. Meaning that each object in the collection has its own unique set of properties (which could have the same property name as the sibling object):
$JSON = ConvertFrom-Json '{
"key1":"key 1 value",
"options":{
"outDir":"./app-dir",
"lib":[
"someLibrary",
"anotherLibrary"
],
"someObjects":[
{
"first":"I am first"
},
{
"first":"I am first too"
},
{
"second":"I am second"
}
]
}
}'
Note that you might actually encounter a object collection at every level of the Json object.
Since PSv3 you have a feature called Member Enumeration which lets you list these properties in ones, like: ([Object[]]$SomeObject).First but you can't just set (all) the concerned properties like this: ([Object[]]$SomeObject).First = $Value. (That is why your SetValue function doesn't work and your GetValue function does. Note that it
actually returns two items for the above "I am first too" Json example).
Answer
In other words, you will need to iterate through all the object collections on each level to set the concerned property:
function SetValue($object, $key, $Value)
{
$p1,$p2 = $key.Split(".",2)
if($p2) { $object | ?{$Null -ne $_.$p1} | %{SetValue -object $_.$p1 -key $p2 -Value $Value} }
else { $object | ?{$Null -ne $_.$p1} | %{$_.$p1 = $Value} }
}
SetValue -object $JSON -key $SearchPath -Value $NewValue
$Json | ConvertTo-Json -Depth 5
{
"key1": "key 1 value",
"options": {
"outDir": "./app-dir",
"lib": [
"someLibrary",
"anotherLibrary"
],
"someObjects": [
{
"first": "I am a new value"
},
{
"second": "I am second"
}
]
}
}

Laravel make array of arrays

How get an array of many array ? foreach line 0-1-2-3(4-5 same object actually), actually objects.
How make it for get:
[ 1[] 2[] 3[4[]5[]] ]
Php code (laravel):
$array = array();
foreach($users as $u)
{
$x = User::where('xxx', 'xxx')->toArray();
array_push($array, $x);
}
return $array;

How to parse through FB Graph API friends list array for specific value, ID?

I successfully loaded the friends array containing more arrays into a variable. But how do I iterate through it to take only the id's out?
I used:
$friends = $facebook->api('/me/friends/');
It returns a multidimensional array like so:
array(1) { ["name"] => "Username" ["id"] => "User ID #"}
array(2) { ["name"] => "Username" ["id"] => "User ID #"}
...and so on...
Any help would be appreciated! Thanks.
Results of Graph API almost always contain data property which is contain all the response data, to get only the friends ids you can look over it in such way:
// If all you need is users ids, specify it in fields url argument
$friends = $facebook->api('/me/friends/?fields=id');
$data = $friends['response'];
$friendsIds = array();
for ($data as $user){
$friendsIds[] = $user['id'];
}
Try:
$yourIdArr = array();
foreach($yourFriendArray as $key => $val) {
if("id" == $key) {
array_push($yourIdArr, $val);
}
}

Resources