In my program i have arrays in the following format . I need to find whether a value is present in an the array
return [
"affiliates" => [
"name" => 'Affiliates',
"value" => 11
],
"business" => [
"name" => 'Business',
"value" => 12
],
"inquiries" => [
"name" => 'Inquiries',
"value" => 13
],
"students" => [
"name" => 'Students',
"value" => 14
],
"teachers" => [
"name" => 'Teachers',
"value" => 15
],
"Personal" => [
"name" => 'Personal',
"value" => 3
],
];
I am doing the following. I am expecting that the search will find the value(12) which is a business, but It is returning false.
$searchcategoryid = '12';
$key = array_search($searchcategoryid, array_column(config('peopletypes.students'), 'value'));
Please note that config('peopletypes.students')will return the array above mentioned. I am using laravel.
You have some sort of configuration problem, this code prints 1.
<?php
$searchcategoryid = '12';
$key = array_search($searchcategoryid, array_column([
"affiliates" => [
"name" => 'Affiliates',
"value" => 11
],
"business" => [
"name" => 'Business',
"value" => 12
],
"inquiries" => [
"name" => 'Inquiries',
"value" => 13
],
"students" => [
"name" => 'Students',
"value" => 14
],
"teachers" => [
"name" => 'Teachers',
"value" => 15
],
"Personal" => [
"name" => 'Personal',
"value" => 3
],
], 'value'));
echo $key;
Try to make sure that your config function actually returns the array you claim it to.
Related
Say I have a collection that looks like this:
$subscriptions = collect([
[
"id" => 1,
"event" => "FormCompleted",
"subscriber" => [
"id" => 2929,
"name" => "Adam",
"email" => "adam#dude.com"
]
],
[
"id" => 3,
"event" => "FormCompleted",
"subscriber" => [
"id" => 1928,
"name" => "Pope",
"email" => "pope#dude.com"
],
],
[
"id" => 4,
"event" => "StatusChanged",
"subscriber" => [
"id" => 2929,
"name" => "Adam",
"email" => "adam#dude.com"
]
]
]);
This shows a list of events with its subscriber. What I want is to re-group this to show a list of subscribers with its events. How do I group these results to get a result like this?
[
[
"id" => 2929,
"name" => "Adam",
"email" => "adam#dude.com",
"subscriptions" => [
[
"id" => 1,
"event" => "FormCompleted"
],
[
"id" => 4,
"event" => "StatusChanged"
],
]
],
[
"id" => 1928,
"name" => "Pope",
"email" => "pope#dude.com",
"subscriptions" => [
[
"id" => 3,
"event" => "FormCompleted"
]
]
]
]
Here is my code... which works, but it is very messy and I feel like there is a better way to do it...
$subscribers = $subscriptions->groupBy('subscriber.id')
->map(function($group) {
$subscriber = $group[0]->subscriber;
$subscriber['subscriptions'] = $group->map(function($subscription) {
unset($subscription['subscriber']);
return $subscription;
});
return $subscriber;
})->values();
I think like that this should return you all subscribers who have groups, so guarantees return not empty subscribers with events
More details you can read this in documention
return Subscriber::has('groups')->get()->groupBy('id');
I have a function which gives an array of the below format
$result = [
[
"name" => "text",
"id" => "928610",
"entity_type" => "node"
],
[
"name" => "folder",
"id" => "987620",
"entity_type" => "folder"
],
[
"name" => "text",
"id" => "956720",
"entity_type" => "node"
],
];
Each Folder "entity_type" => "folder" item has again child which returns same format array.
like if we run a foreach loop $result and if it is "entity_type" => "folder" then we pass the id to a function it will also give a similar array format as that of result.
So i need if it is "entity_type" => "folder" the below key added to the "entity_type" => "folder" item
"children" => [
'#theme' => 'child_elements',
'#child_elements' => [
[
'name' => 'text',
"id" => "333421",
"entity_type" => "node"
],
[
'name' => 'folder',
"id" => "897622",
"entity_type" => "folder"
],
[
'name' => 'text',
"id" => "342214",
"entity_type" => "node"
],
],
],
and recursively it should keep on adding if "entity_type" => "folder"
The final array should be
$result = [
[
"name" => "text",
"id" => "928610",
"entity_type" => "node"
],
[
"name" => "folder",
"id" => "987620",
"entity_type" => "folder"
"children" => [
'#theme' => 'child_elements',
'#child_elements' => [
[
'name' => 'text',
"id" => "333421",
"entity_type" => "node"
],
[
'name' => 'folder',
"id" => "897622",
"entity_type" => "folder"
],
[
'name' => 'text',
"id" => "342214",
"entity_type" => "node"
],
],
],
],
[
"name" => "text",
"id" => "956720",
"entity_type" => "node"
],
];
public function buildTree($elements) {
$branch = [];
$branch = ['#theme' => 'child_elements'];
foreach ($elements as $key => $element) {
foreach($element as $keys => $values){
if ($element['bundle'] == 'folder') {
$child = $this->loadElements($element['id']);
$branch['#child_elements'] = $child;
$element[$key]['children'] = $branch['#child_elements'];
$this->buildTree($child);
array_push($branch, $element);
}else{
$branch['#child_elements'][] = $element;
}
}
}
return $branch;
}
you need to use some logic statement and use array_push when the condition is met.
I have a problem with multidimensional data arrays. I have a data array like this:
[
[
"name" => "netSnmp",
"oid" => "1.3.6.1.4.1.8072"
"status" => "current"
], [
"name" => "netSnmpObjects",
"oid" => "1.3.6.1.4.1.8072.1"
], [
"name" => "netSnmpEnumerations",
"oid" => "1.3.6.1.4.1.8072.3"
], [
"name" => "netSnmpModuleIDs",
"oid" => "1.3.6.1.4.1.8072.3.1"
], [
"name" => "netSnmpAgentOIDs",
"oid" => "1.3.6.1.4.1.8072.3.2"
], [
"name" => "netSnmpDomains",
"oid" => "1.3.6.1.4.1.8072.3.3"
], [
"name" => "netSnmpNotificationPrefix",
"oid" => "1.3.6.1.4.1.8072.4"
], [
"name" => "netSnmpNotifications",
"oid" => "1.3.6.1.4.1.8072.4.0"
], [
"name" => "netSnmpNotificationObjects",
"oid" => "1.3.6.1.4.1.8072.4.1"
]
]
I am looking for a simple way to create an array tree, based on the oid value from the array above. Those oid values are a dot-separated path. The more parts, the deeper in the final tree the corresponding item should be put.
The desired output:
[
"text" => "netSnmp",
"oid" => "1.3.6.1.4.1.8072",
"nodes" => [
[
"oid" => "1.3.6.1.4.1.8072.1",
"text" => "netSnmpObjects"
], [
"oid" => "1.3.6.1.4.1.8072.3",
"text" => "netSnmpEnumerations",
"nodes" => [
[
"text" => "netSnmpModuleIDs",
"oid" => "1.3.6.1.4.1.8072.3.1"
], [
"text" => "netSnmpAgentOIDs",
"oid" => "1.3.6.1.4.1.8072.3.2"
], [
"text" => "netSnmpDomains",
"oid" => "1.3.6.1.4.1.8072.3.3"
]
]
], [
"oid" => "1.3.6.1.4.1.8072.4",
"text" => "netSnmpNotificationPrefix"
"nodes" => [
[
"text" => "netSnmpNotifications",
"oid" => "1.3.6.1.4.1.8072.4.0"
], [
"text" => "netSnmpNotificationObjects",
"oid" => "1.3.6.1.4.1.8072.4.1"
]
]
]
]
]
Any idea how I can solve it?
You can key your data by oid in a new associated array: that way you can look up a certain parent key in a fast way.
Then it is just a matter of getting the parent key of a any given key (chopping off the final dot-separated part) and see where you have it in your new associated array, and then appending it to its nodes array.
Here is a function that does that:
function makeTree($arr) {
$keyed = [];
foreach ($arr as $item) $keyed[$item["oid"]] = $item;
$root = null;
foreach ($keyed as &$item) {
$key = $item["oid"];
$parent = substr($key, 0, strrpos($key, "."));
if (isset($keyed[$parent])) {
$keyed[$parent]["nodes"][] =& $item;
} else {
$root = $key;
}
}
return $keyed[$root];
}
You can run it like this on your sample data:
$arr = [
[
"name" => "netSnmp",
"oid" => "1.3.6.1.4.1.8072",
"status" => "current"
], [
"name" => "netSnmpObjects",
"oid" => "1.3.6.1.4.1.8072.1"
], [
"name" => "netSnmpEnumerations",
"oid" => "1.3.6.1.4.1.8072.3"
], [
"name" => "netSnmpModuleIDs",
"oid" => "1.3.6.1.4.1.8072.3.1"
], [
"name" => "netSnmpAgentOIDs",
"oid" => "1.3.6.1.4.1.8072.3.2"
], [
"name" => "netSnmpDomains",
"oid" => "1.3.6.1.4.1.8072.3.3"
], [
"name" => "netSnmpNotificationPrefix",
"oid" => "1.3.6.1.4.1.8072.4"
], [
"name" => "netSnmpNotifications",
"oid" => "1.3.6.1.4.1.8072.4.0"
], [
"name" => "netSnmpNotificationObjects",
"oid" => "1.3.6.1.4.1.8072.4.1"
]
];
$result = makeTree($arr);
print_r($result);
I'm struggling to update a document and add new elements (fields) into it's existing array without losing the array elements on update.
This is my code which inserts a new document into the collection if it doesn't already exist (upsert):
$updateResult = $collection->findOneAndUpdate(
[
'recording-id' => $out['recording']->id
],
['$set' => [
'release' => [
'id' => $out['release']->id,
'title' => $out['release']->title,
'date' => $out['release']->date,
'country' => $out['release']->country
],
'artist' => [
'id' => $out['artist']->id,
'name' => $out['artist']->name,
],
'recording' => [
'id' => $out['recording']->id,
'title' => $out['recording']->title,
'score' => $out['recording']->score,
'length' => $out['recording']->length,
'release-count' => count($out['recording']->releases),
],
'release-group' => [
'id' => $out['release-group']['id'],
'title' => $out['release-group']['title'],
'first-release-date'=>$out['release-group']['first-release-date'],
'primary-type' => $out['release-group']['primary-type'],
'musicbrainz' => $out['release-group']['musicbrainz'],
'url-rels' => $out['release-group']['url-rels'],
'coverart' => $out['release-group']['coverart']
],
'execution' => [
'firstfind' => $out['execution']->time
]
]
],
['upsert' => true,
'projection' =>
[
'_id' => 0,
'release' => 1,
'artist' => 1,
'recording' => 1,
'release-group' => 1,
'execution' => 1
],
'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
]
);
So now I have an existing document in a collection:
{
"_id" : ObjectId("5d1a6aaf5ecc8001ee858f6c"),
"recording-id" : "d0d439f9-5324-4728-8706-2da39adb89c5",
"artist" : {
"id" : "9d97b077-b28d-4ba8-a3d9-c71926e3b2b6",
"name" : "Gordon Lightfoot"
},
"recording" : {
"id" : "d0d439f9-5324-4728-8706-2da39adb89c5",
"title" : "Sundown",
"score" : 100,
"length" : 184000,
"release-count" : 2
},
"release" : {
"id" : "0c008d76-2bc9-44a3-854b-0a08cde89337",
"title" : "All Live",
"date" : "2012-04-24",
"country" : "CA"
},
"release-group" : {
"id" : "0a5d5f33-8e9d-4fa4-b622-a95e4218a3c4",
"title" : "All Live",
"first-release-date" : "2012-04-24",
"primary-type" : "Album",
"musicbrainz" : "https://musicbrainz.org/release-group/0a5d5f33-8e9d-4fa4-b622-a95e4218a3c4",
"url-rels" : "https://musicbrainz.org/ws/2/release-group/0a5d5f33-8e9d-4fa4-b622-a95e4218a3c4?inc=url-rels&fmt=json",
"coverart" : null
}
}
Now, I would like to update this document, and add new fields into the arrays. The new fields are to be added to certain fields.
Here is the code doing that:
$collection = (new MongoDB\Client)->stream->musicbrainz;
$updateResult = $collection->updateOne(
[
'recording-id' => $out['recording']['id']
],
['$addToSet' => [
'artist' => [
'wikiQiD' => $out['artist']['qid'],
'wiki-extract' => $out['artist']['wiki-extract'],
'wiki-pageid' => $out['artist']['pageid'],
],
'release-group' => [
'wikiQiD' => $out['release-group']['qid'],
'wiki-extract' => $out['release-group']['wiki-extract']
]
]
],
[
'upsert' => true,
'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
]
);
I've noticed there's "$addToSet" and "$push" commands, and could use assistance with what the difference is between these two commands.
If the field is absent in the document to update, $push adds the array
field with the value as its element.
The $addToSet operator adds a value to an array unless the value is
already present, in which case $addToSet does nothing to that array.
I did some googling, and reading of the MongoDB/Client UpdateOne function, but can't seem to find a way to append these fields to the existing arrays.
The error I'm getting is:
Fatal error: Uncaught MongoDB\Driver\Exception\BulkWriteException: The field 'artist' must be an array but is of type object in document {_id: ObjectId('5d1a6aaf5ecc8001ee858f6c')} in ...
I know the following:
It could be my document, as it's not a proper array that Fatal error is complaining about.
It could be my `findOneAndUpdate' formatting, and I'm not doing that correctly.
It could be both and I have it all wrong from the very start.
Any insight or constructive criticism is appreciated, just refrain from flames, pls.
Here's the working code I finally use to get it do what I want it to.
It's a simple matter of just setting your field names and values and mongo will update the found record replacing it with the array sent to it. No need to push or anything.
function firstFindMongoUpdate($out) {
$collection = (new MongoDB\Client)->stream->musicbrainz;
$updateResult = $collection->findOneAndUpdate(
[
'recording-id' => $out['recording']->id
],
['$set' => [
'query' => $out['query'],
'release' => [
'id' => $out['release']->id,
'title' => $out['release']->title,
'date' => $out['release']->date,
'country' => $out['release']->country,
'label' => $out['release']->label,
],
'artist' => [
'id' => $out['artist']->id,
'name' => $out['artist']->name,
'wiki' => $out['artist']->wiki,
],
'recording' => [
'id' => $out['recording']->id,
'title' => $out['recording']->title, // sometimes contains apostophe ie; Bill‘s Love (option ] key)
'score' => $out['recording']->score,
'length' => $out['recording']->length,
'release-count' => count($out['recording']->releases)
],
'release-group' => [
'id' => $out['release-group']['id'],
'title' => $out['release-group']['title'],
'first-release-date'=>$out['release-group']['first-release-date'],
'primary-type' => $out['release-group']['primary-type'],
'musicbrainz' => $out['release-group']['musicbrainz'],
'url-rels' => $out['release-group']['url-rels'],
'coverart' => $out['release-group']['coverart'],
'wiki' => $out['release-group']['wiki']
],
'execution' => [
'artistQuery' => $out['execution']->artistQuery,
'recordingQuery'=> $out['execution']->recordingQuery,
'time' => $out['execution']->time
]
]
],
['upsert' => true,
'projection' =>
[
'_id' => 1,
'query' => 1,
'release' => 1,
'artist' => 1,
'recording' => 1,
'release-group' => 1,
'execution' => 1
],
'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
]
);
I have this array coming from post request:
$x = [
"meal" => [
"monday" => [
"breakfast" => [
0 => "type1",
1 => "type1",
],
"afternoonTea" => [
0 => "type2",
],
],
],
"number" => [
"monday" => [
"breakfast" => [
0 => "10",
1 => "9",
],
"afternoonTea" => [
0 => "1",
],
],
],
];
I am trying to merge all this into one array without using tones of foreaches.
Maybe someone more clever will know how to use iterators to achieve that.
Data from meal and number is always 1:1.
I need to convert this to something like this:
$x = [
"monday" => [
"breakfast" => [
[
'type' => "type1",
'number' => 10,
],
[
'type' => "type1",
'number' => 9
]
],
"afternoonTea" => [
[
'type' => "type2",
'number' => 1,
],
],
],
],
];
If you count 3 as being tonnes then this isn't your answer - but I can't see a way of reducing down the number of reach loops below this without getting to a game of code golf which won't be helpful.
Because you know there is a 1:1 relationship between meal and number, you can use the indexes from one to get data from the other by doing:
$result = [];
foreach($x['meal'] as $day => $list) {
foreach($list as $activity => $types) {
foreach($types as $i => $type) {
$result[$day][$activity][] = [
'type' => $type,
'value' => $x['number'][$day][$activity][$i],
];
}
}
}
The output of this will be $result will contain the array in the format you want.