Finding distinct and removing duplicates from object [duplicate] - c#

This question already has answers here:
Remove duplicates in the list using linq
(11 answers)
Closed 2 years ago.
I am very new to LINQ. I have run to a scenario where I need to find distinct from an object and remove the others. Please help.
I have tried like this
var xyz = referal.GroupBy(i => i.Select(x => x.identifier).Distinct().Select(g=>g));
but it is not returning the distinct values. Thanks in advance.
Sample Object :
{
"referral_type": [
{
"type": "MOBILE",
"invitee": [
{
"identifier": "12345678",
"name": "Test2",
"invited_on": "2020-01-29 12:25:46.0",
"till": {
"code": "",
"name": ""
}
},
{
"identifier": "98765432",
"name": "Test1",
"invited_on": "2020-01-29 13:37:36.0",
"till": {
"code": "",
"name": ""
}
},
{
"identifier": "12345678",
"name": "Harry Test",
"invited_on": "2020-01-29 13:55:32.0",
"till": {
"code": "",
"name": ""
}
},
{
"identifier": "98765432",
"name": "Harry Test",
"invited_on": "2020-01-29 13:55:32.0",
"till": {
"code": "",
"name": ""
}
}
]
}
]
}
So I want to check the distinct identifier and take the first one irresoective of other values, something like this
{
"referral_type": [
{
"type": "MOBILE",
"invitee": [
{
"identifier": "12345678",
"name": "Test2",
"invited_on": "2020-01-29 12:25:46.0",
"till": {
"code": "",
"name": ""
}
},
{
"identifier": "98765432",
"name": "Test1",
"invited_on": "2020-01-29 13:37:36.0",
"till": {
"code": "",
"name": ""
}
}
]
}
]
}

You need to implement the interface IEquatable<T> class "invitee", because Dinstinct use this to compare object. On this way i think you are comparing memory references.

Related

How to fetch collection of subdocument using mongodb C# driver?

I have following MongoDB document:
{
"_id": {
"$oid": "5fbfa0005c15aaf2eac69ba6"
},
"PostMedia": [
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img1.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img2.jpg",
"Title": null,
"Description": ""
}
]
},
{
"_id": {
"$oid": "5fbfa0485c15aaf2eac69ba7"
},
"PostMedia": [
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img3.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img4.jpg",
"Title": null,
"Description": ""
}
]
}
and I want to fetch all PostMedia to single array using MongoDB C# driver.
Here is the expected result:
[
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img1.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img2.jpg",
"Title": null,
"Description": ""
}, {
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img3.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img4.jpg",
"Title": null,
"Description": ""
}
]
I had tried to use group aggregation function but it returned an array of array.
Result I received:
PostMedia:[{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img1.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img2.jpg",
"Title": null,
"Description": ""
}],[
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img3.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img4.jpg",
"Title": null,
"Description": ""
}
]
C# code I have written so far is as follows:
var group = new[]
{
new BsonDocument("$group",
new BsonDocument
{
{ "_id", BsonNull.Value },
{ "PostMedia", new BsonDocument("$push", "$PostMedia") }
})
};
var result = collection.Aggregate<MediaList>(group).FirstOrDefault();
return list;
}
Is there any way to fetch subdocument by merging them is a single array.
You have to $unwind before $group,
$unwind deconstruct PostMedia array
$replaceRoot replace PostMedia object to root
$unset remove _id field
{ $unwind: "$PostMedia" },
{
$group: {
_id: null,
PostMedia: { $push: "$PostMedia" }
}
},
{ $unset: "_id" } // remove field
Playground
C#:
new BsonArray
{
new BsonDocument("$unwind", "$PostMedia"),
new BsonDocument("$group",
new BsonDocument
{
{ "_id", BsonNull.Value },
{ "PostMedia",
new BsonDocument("$push", "$PostMedia") }
})
new BsonDocument("$unset", "_id")
}

NEST Elastic Search - query a term with spaces

I'm having hard time implementing autocomplete in elastic for DisplayName property for the text that have spaces in it, here is the setup of the field:
"DisplayName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256,
"normalizer": "caseinsensitive"
},
"prefix": {
"type": "text",
"analyzer": "startswith"
}
}
},
"id": {
"type": "keyword"
}
Here is the startwith analyzer definition:
"analysis": {
"analyzer": {
"startswith": {
"char_filter": [
"html_strip"
],
"filter": [
"lowercase"
],
"tokenizer": "keyword",
"type": "custom"
}
},
"normalizer": {
"caseinsensitive": {
"filter": [
"lowercase",
"asciifolding"
],
"type": "custom"
}
}
},
"creation_date": "1565034410554",
"mapping": {
"total_fields": {
"limit": "5000"
}
},
"number_of_shards": "5",
"provided_name": "streetsmart"
In my query builder here is the query that tries to grab the result:
_type:User AND (DisplayName.prefix:Joseph adam* OR UserPrincipalName.prefix:Joseph adam*)"
and the result that I get is all the names that contains Adam which the result should be Joseph Adam Jr,
Does anyone know what I should do?
I am not aware of c# and .net syntax, but adding a working example with index data, search query, and search result in JSON format.
You can also use Match phrase prefix query that :
Returns documents that contain the words of a provided text, in the
same order as provided. The last term of the provided text is treated
as a prefix, matching any words that begin with that term.
Index Data:
{
"name": "Adam"
}
{
"name": "Joseph Adam Sr"
}
{
"name": "Joseph Adam Jr"
}
Search Query:
{
"query": {
"multi_match": {
"query": "Joseph Adam",
"fields": [
"name"
],
"type": "phrase_prefix"
}
}
}
Search Result:
"hits": [
{
"_index": "stof_64163994",
"_type": "_doc",
"_id": "1",
"_score": 0.54037446,
"_source": {
"name": "Joseph Adam Jr"
}
},
{
"_index": "stof_64163994",
"_type": "_doc",
"_id": "3",
"_score": 0.54037446,
"_source": {
"name": "Joseph Adam Sr"
}
}
]

c# json deserialization complex objects

I have a problem deserializing a json file, this is the json:
[
{
"id": "id",
"number": "48",
"date": "17-01-2020",
"details": [
{
"id": "id",
"code": "code",
"description": "desc"
},
{
"id": "id",
"code": "code",
"description": "desc"
}
],
"address": "add",
"note": null
},
{
"id": "id",
"number": "55",
"date": "17-01-2020",
"details": [
{
"id": "id",
"code": "code",
"description": "desc"
},
{
"id": "id",
"code": "code",
"description": "desc"
}
],
"address": "add",
"note": null
}
]
this is my code:
var result = httpClient.GetAsync(".....").Result;
List<Docu> doc= new JavaScriptSerializer().Deserialize<List<Docu>>(result.Content.ReadAsStringAsync().Result);
class Docu contains definition of id, number, date, details and:
public List<Details> det{ get; set; }
Class Details contains id, code and description definition
I can deserialize everything except complex object details, it returns null from deserialization, how I can fix this? I need to fill the list of details
You have wrong name for List<Details> property
it should be
public List<Details> details{ get; set; }
according to json you have shown

Actions on google correct response

My C# web API has successfully received a request from my Actions on google dialog flow. But I am having issues understanding what the response format should be.
{
"responseId": "96ee6c11-8f73-409f-8dac-8b6141d08483",
"queryResult": {
"queryText": "History",
"action": "tell.fact",
"parameters": {
"category": "history"
},
"allRequiredParamsPresent": true,
"fulfillmentMessages": [
{
"text": {
"text": [
""
]
}
}
],
"outputContexts": [
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/google_assistant_input_type_touch",
"parameters": {
"category.original": "History",
"category": "history"
}
},
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/actions_capability_screen_output",
"parameters": {
"category.original": "History",
"category": "history"
}
},
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/choose_fact-followup",
"lifespanCount": 2,
"parameters": {
"category.original": "History",
"category": "history"
}
},
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/actions_capability_audio_output",
"parameters": {
"category.original": "History",
"category": "history"
}
},
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/actions_capability_media_response_audio",
"parameters": {
"category.original": "History",
"category": "history"
}
},
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/actions_capability_web_browser",
"parameters": {
"category.original": "History",
"category": "history"
}
}
],
"intent": {
"name": "projects/project--6162817918903295576/agent/intents/4a35cf33-e446-4b2b-a284-c70bc4dfce17",
"displayName": "choose_fact"
},
"intentDetectionConfidence": 1,
"languageCode": "en-us"
},
"originalDetectIntentRequest": {
"source": "google",
"version": "2",
"payload": {
"isInSandbox": true,
"surface": {
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name": "actions.capability.WEB_BROWSER"
}
]
},
"requestType": "SIMULATOR",
"inputs": [
{
"rawInputs": [
{
"query": "History",
"inputType": "TOUCH"
}
],
"arguments": [
{
"rawText": "History",
"textValue": "History",
"name": "text"
}
],
"intent": "actions.intent.TEXT"
}
],
"user": {
"lastSeen": "2018-07-06T11:44:24Z",
"locale": "en-US",
"userId": "AETml1TDDPgKmK2GqQ9ugHJc5hQM"
},
"conversation": {
"conversationId": "1530877719318",
"type": "ACTIVE",
"conversationToken": "[]"
},
"availableSurfaces": [
{
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.WEB_BROWSER"
}
]
}
]
}
},
"session": "projects/project--6162817918903295576/agent/sessions/1530877719318"
}
attempt one
The documentation webhook states that my response should look like that
{"fulfillmentText":"Hello from C# v2","fulfillmentMessages":[{"card":{"title":"card title","subtitle":"sub title","imageUri":"https://assistant.google.com/static/images/molecule/Molecule-Formation-stop.png","buttons":[{"text":"button text","postback":"https://assistant.google.com/"}]}}],"source":"example.com","payload":{"google":{"expectUserResponse":true,"richResponse":{"items":[{"simpleResponse":{"textToSpeech":"Thi sis a simple response "}}]}},"facebook":{"text":"Hello facebook"},"slack":{"text":"Hello facebook"}},"outputContexts":[{"name":"projects/project--6162817918903295576/agent/sessions/2a210c67-4355-d565-de81-4d3ee7439e67","lifespanCount":5,"parameters":{"param":"parm value"}}],"followupEventInput":{"name":"event name","languageCode":"en-Us","parameters":{"param":"parm value"}}}
This results in the following error
MalformedResponse 'final_response' must be set.
Failed to parse Dialogflow response into AppResponse because of empty speech response
attempt 2
So i went on to try simple response
{
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "this is a simple response"
}
}
]
}
}
}
}
Which also results with
MalformedResponse 'final_response' must be set.
Failed to parse Dialogflow response into AppResponse because of empty speech response
I can verify that my requests are being sent as application/json
Does anyone know the proper response format?
The root problem is actually ASP.NET Core by default uses transfer-encoding: chunked for ActionResult and for some reason Dialogflow does not support parsing chunked transfer
The following response is accepted by actions.
[HttpPost]
public ContentResult Post([FromBody] FulfillmentRequst data)
{
var response = new FulfillmentResponse
{
fulfillmentText = "Hello from C# v2",
};
return Content(JsonConvert.SerializeObject(response), "application/json");
}
Here is the JSON response format: https://github.com/dialogflow/fulfillment-webhook-json/blob/master/responses/v2/response.json

Extracting elements wherever JArray in json

Lets see, the json can be dynamic and can probably have number of nested arrays within any property.
Example:
{
"items": [
{
"id": "0001",
"name": "Cake",
"batters": {
"batter": [
{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate"
},
{
"dry": [
{
"id": "1003",
"type": "Devil's Food"
}
]
}
],
"other": [
{
"id": "1004",
"type": "Home Food"
}
]
},
"topping": [
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
}
]
},
{
"id": "0002",
"name": "Sweets"
}
]
}
A simple list should return elements as:
[
{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate"
},
{
"id": "1003",
"type": "Devil's Food"
},
{
"id": "1004",
"type": "Home Food"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
},
{
"id": "0002",
"name": "Sweets"
}
]
Please note:
Json can by anything, no property can be used for extraction , just knowing that what needed is stuff inside an JArray.
What i have tried so far but its just a start:
public static bool ParseJsonArray(JToken token, List<string> extracts, string parentLocation = "")
{
if (token.HasValues)
{
foreach (JToken child in token.Children())
{
if (token.Type == JTokenType.Array)
{
parentLocation += ((JProperty)token).Name;
extracts.Add(token.ToString());
}
ParseJsonArray(child, extracts, parentLocation);
}
return true;
}
else
{
return false;
}
}
token here is the parsed dynamic json.
It appears as though you want to recursively find all JArray entries that do not themselves contain nested arrays. Let's call these "leaf" array entries. I say that because you don't include the following non-leaf entry in your results:
{
"id": "0001",
"name": "Cake"
}
That being said, you can find leaf array entries with the following extension method:
public static class JsonExtensions
{
public static IEnumerable<JToken> LeafArrayEntries(this JContainer container)
{
var nonLeafEntries = new HashSet<JToken>(container.DescendantsAndSelf()
.OfType<JArray>()
.SelectMany(a => a.Ancestors().Where(p => p.Type != JTokenType.Property)));
return container.DescendantsAndSelf().Where(c => c.Parent is JArray && !nonLeafEntries.Contains(c));
}
}
Then put the returned items in an array of their own with:
var leafItemArray = new JArray(rootJContainer.LeafArrayEntries());

Categories

Resources