Convert flat to hierarchy list? - c#

I have two tables "CategoryGroup" and "Category" which returns data in one list. Requirement is to convert flat list to hierarchy list like CategoryGroup contains related categories.
Please suggest how to convert into hieararchy list?
public class ProfileConditionGroup
{
public Guid ConditionGroupGUID { get; set; }
public string ConditionGroupName { get; set; }
public List<ProfileConditionList> profileConditions { get; set; }
}
public class ProfileConditionList
{
public string ConditionName { get; set; }
public Nullable<Guid> ConditionGUID { get; set; }
public string[] ThisConditionSelectedByProfileIDs { get; set; }
public Nullable<Guid> ParentConditionGroupGUID { get; set; }
public bool IsDefaultSelected { get; set; }
}

This is actually a little tricky without having an actual concrete return type, but here's the way I'd tackle it if you're just building a tree of Guid values.
Given this query:
var query =
from pcg in pcgs
from pcl in pcg.profileConditions
select new
{
pcg.ConditionGroupName,
pcg.ConditionGroupGUID,
pcl.ConditionName,
pcl.ConditionGUID,
pcl.ThisConditionSelectedByProfileIDs,
pcl.ParentConditionGroupGUID,
pcl.IsDefaultSelected,
};
...I'd do this:
var lookup = query.ToLookup(x => x.ParentConditionGroupGUID);
Func<Guid?, Tree<Guid?>> build = null;
build = g =>
{
var r = new Tree<Guid?>() { Value = g };
r.AddRange(lookup[g].Select(x => build(x.ConditionGroupGUID)));
return r;
};
Now you just call build(null) and you should get a tree of Guid?. If you can create you're own output class you'd change the function to Func<Guid?, Tree<YourOutputClass>>.
You need this class for the tree:
public class Tree<T> : List<Tree<T>>
{
public T Value { get; set; }
}

Related

Display the fields of the class in order by position in a list

I have this class:
public class Presenter
{
public int? Society { get; set; }
public int? SenderCode { get; set; }
public string BusinessNameSender { get; set; }
public string AddressSender { get; set; }
public string VatNumberSender { get; set; }
public string Check { get; set; }
}
Retrieve the data with a query and with the ExtractField method populate the Presenter class
public static IEnumerable<Presenter> ExtractField(IEnumerable<dynamic> query)
{
return query.Select(x => new Presenter()
{
Society = x.ids.Society ?? null,
SenderCode = x.ids.SenderCode ?? null,
BusinessNameSender = x.details.Sender,
AddressSender = x.details.DestinationAddress,
VatNumberSender = x.details.VatNumberSender,
Check = x.ids.Check,
});
}
When I then use the ToList() to then display the result on the screen within the list, the fields are sorted alphabetically, how do I make sure that the fields are seen in the order I have set?
I used dynamic because having two distinct queries but which have the same select seemed to me the best way not to duplicate code

Dynamic Linq Filtering with Parent Property not working

I have question related to dynamic Linq.
I have a class structure defined as below.
public class UserProfile
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public long Overtime { get; set; }
public UserProfileDetails UserProfileDetails { get; set; }
}
public class UserProfileDetails
{
public UserProfileDetails()
{
LstString = new List<string>();
}
public string Department { get; set; }
public double Salary { get; set; }
public int LeaveBalance { get; set; }
public List<string> LstString { get; set; }
}
Created a object of UserProfile like given below.
var a = new UserProfile();
For a normal Linq I can execute the following. I am trying to find all the strings in UserProfileDetails while is not same a my first name.
var vvv = a.UserProfileDetails.LstString.Where(x => !x.Equals(a.FirstName)).ToList();
I want to convert the above linq to dynamic linq and used the following
var vDyna = a.UserProfileDetails.LstString.AsQueryable().Where("!Equals(FirstName)").ToList();
But the above is giving the error:
System.Linq.Dynamic.Core.Exceptions.ParseException: 'No property or field 'FirstName' exists in type 'String''.
Can anyone help me with this please?
I think it's similar to the LINQ function. In the where string you have to use the UserProfile variable a.
Your Code:
var vDyna = a.UserProfileDetails.LstString.AsQueryable().Where("!Equals(FirstName)").ToList();
My suggestion:
var vDyna = a.UserProfileDetails.LstString.AsQueryable().Where(s => !s.Equals(a.FirstName)).ToList();
I never used Dynamic Linq, but maybe that helps.
Source:
https://learn.microsoft.com/en-us/dotnet/api/system.linq.queryable.where?view=net-5.0
EDIT 1:
var vDyna = a.UserProfileDetails.LstString.AsQueryable().Where("!Equals(#0)", a.FirstName).ToList();

Obtaining HashSet and Dictionary, grouping by nested property, from List in C#

Sorry I am a newbie in C#, I come from Java 8.
I was checking the code in C#,
In namespace IBM.Watson.Assistant.v1.Model
public class LogCollection
{
public LogCollection();
public List<Log> Logs { get; set; }
public LogPagination Pagination { get; set; }
}
In the same namespace the classes:
class Log
public class Log
{
public Log();
public MessageRequest Request { get; set; }
public MessageResponse Response { get; set; }
public string LogId { get; set; }
public string RequestTimestamp { get; set; }
public string ResponseTimestamp { get; set; }
public string WorkspaceId { get; set; }
public string Language { get; set; }
}
class MessageResponse
public class MessageResponse
{
public MessageResponse();
public MessageInput Input { get; set; }
public List<RuntimeIntent> Intents { get; set; }
public List<RuntimeEntity> Entities { get; set; }
public bool? AlternateIntents { get; set; }
public Context Context { get; set; }
public OutputData Output { get; set; }
public virtual List<DialogNodeAction> Actions { get; }
}
And the class Context
public class Context : DynamicModel<object>
{
public Context();
public string ConversationId { get; set; }
public Dictionary<string, object> System { get; set; }
public MessageContextMetadata Metadata { get; set; }
}
Now I have
List<IBM.Watson.Assistant.v1.Model.Log> listLog = logCollection.Logs;
I would like to get the distinct ConversationId into a HashSet (or get a HashSet from nested property of object List).
In Java 8 I would use:
Set<String> setConversationId = listLog.stream()
.map(log -> log.getResponse().getContext().getConversationId())
.collect(Collectors.toSet());
In C# - can I do something like this?
HashSet<string> setConversationId = new HashSet<string>(listLog.HOW_TO_GET_ConversationId_FROM_Context_FROM_Response);
Now, I would like to group the logs by ConversationId into a dictionary.
In Java 8 is something like:
public Map<String, List<Log>> getMapFromList(List<Log> listLog)
{
Map<String, List<Log>> map = listLog
.stream().collect(Collectors.groupingBy(
log -> log.getResponse().getContext().getConversationId(),
Collectors.mapping(log -> log, Collectors.toList())
));
return map;
}
In C#
public Dictionary<string, List<Log>> getDictionaryFromList(List<Log> listLog)
{
Dictionary<string, List<Log>> dictionary = listLog
.???????;
return dictionary;
}
How to group data into a dictionary by nested property of some list?
NOTE: I prefer functional/lambda instead of Linq response.
If I understand the question. I am guessing you just want GroupBy, and ToDictionary, which will produce a Dictionary<string,List<Log>>
Given
var list = new List<Log>(){...};
Usage
var dict = list
.GroupBy(x => x.Response.Context.ConversationId)
.ToDictionary(x => x.Key, x => x.ToList());
To get the HashSet
var hashSet = list
.Select(x => x.Response.Context.ConversationId)
.ToHashSet();
Additional Resources
GroupBy<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>)
Groups the elements of a sequence according to a specified key
selector function.
Enumerable.ToDictionary Method
Creates a Dictionary<TKey,TValue> from an IEnumerable<T>.

AutoMapper complex type objects mapping C#

In my method I got back results that contain several list of strings and list of complex type objects.
var AcctLst = gd.validateGroupMembershipUploadDetails(_input);
Mapper.CreateMap<Data.Entities.Upload.GroupMembershipValidationOutput, Business.Upload.GroupMembershipValidationOutput>();
var result = Mapper.Map<Data.Entities.Upload.GroupMembershipValidationOutput, Business.Upload.GroupMembershipValidationOutput>(AcctLst);
return result;
var AcctLst contains the sample data :
Data.Entities.Upload.GroupMembershipValidationOutput
and
Business.Upload.GroupMembershipValidationOutput
looks like
public class GroupMembershipValidationOutput
{
public List<string> _validMasterIds { get; set; }
public List<ChapterCodeValidationOutput> _validChapterCodes { get; set; }
public List<GroupCodeValidationOutput> _validGroupCodes { get; set; }
public List<string> _invalidMasterIds { get; set; }
public List<string> _invalidChapterCodes { get; set; }
public List<string> _invalidGroupCodes { get; set; }
}
public class ChapterCodeValidationOutput
{
public string chpt_cd { get; set; }
public string appl_src_cd { get; set; }
}
public class GroupCodeValidationOutput
{
public string grp_cd { get; set; }
public string grp_nm { get; set; }
}
I guess _validChapterCodes and _validGroupCodes throw the following exception :
Missing type map configuration or unsupported mapping.
Mapping types:
ChapterCodeValidationOutput -> ChapterCodeValidationOutput
ARC.Donor.Data.Entities.Upload.ChapterCodeValidationOutput -> ARC.Donor.Business.Upload.ChapterCodeValidationOutput
Destination path:
GroupMembershipValidationOutput._validChapterCodes._validChapterCodes._validChapterCodes0[0]
Source value:
ARC.Donor.Data.Entities.Upload.ChapterCodeValidationOutput
Yeah damn. It's relatively simple. You just have to map the inner nested types first.
var AcctLst = gd.validateGroupMembershipUploadDetails(_input);
Mapper.CreateMap<Data.Entities.Upload.ChapterCodeValidationOutput, Business.Upload.ChapterCodeValidationOutput>();
Mapper.CreateMap<Data.Entities.Upload.GroupCodeValidationOutput, Business.Upload.GroupCodeValidationOutput>();
Mapper.CreateMap<Data.Entities.Upload.GroupMembershipValidationOutput, Business.Upload.GroupMembershipValidationOutput>();
var result = Mapper.Map<Data.Entities.Upload.GroupMembershipValidationOutput, Business.Upload.GroupMembershipValidationOutput>(AcctLst);
return result;
Then it works flawlessly.

LINQ Selecting a List within a List

I'm trying to fill a list within a list using LINQ to query my database.
The issue I'm facing is that I'm unsure how to select the data into the child list.
When trying to execute the code below, I receive the error
Error 1 Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?)
The model classes are like so:
public class _LayoutViewModel
{
public List<CallGuideMenuL1> CGL1 { get; set; }
}
public class CallGuideMenuL1
{
public string Area { get; set; }
public List<CallGuideMenuL2> Products { get; set; }
}
public class CallGuideMenuL2
{
public int CallGuideProductId { get; set; }
public string Product { get; set; }
}
And the DB context:
public class CallGuideArea
{
public int CallGuideAreaId { get; set; }
public string Area { get; set; }
public List<CallGuideProduct> CallGuideProducts { get; set; }
}
public class CallGuideProduct
{
public int CallGuideProductId { get; set; }
public string Product { get; set; }
public int CallGuideAreaId { get; set; }
public DateTime Added { get; set; }
public DateTime? Deleted { get; set; }
}
In my controller I'm trying to select the data like so:
_LayoutViewModel vm = new _LayoutViewModel();
vm.CGL1 = from a in db.CallGuideArea
.SelectMany(p => p.CallGuideProducts)
select a;
I'm pretty sure it's the select a; line that's the issue as I need to assign the data back to the properties of both CallGuideMenuL1 and CallGuideMenuL2.
Could anyone point me in the right direction around the right LINQ expression?
vm.CGL1 = db.CallGuideArea.Select(a => new CallGuideMenuL1()
{
Area = a.Area,
Products = a.CallGuideProducts.Select(p => new CallGuideMenuL2()
{
CallGuideProductId = p.CallGuideProductId,
Product = p.Product
}).ToList()
}).ToList();
Probably vm.CGL1 is declared as List so you need to select into List:
vm.CGL1 = (from a in db.CallGuideArea
.SelectMany(p => p.CallGuideProducts)
select a).ToList();
or you will need to project:
vm.CGL1 = (from a in db.CallGuideArea
.SelectMany(p => p.CallGuideProducts)
select new CallGuideMenuL1()
{
Area = a.--some property
...
}).ToList();

Categories

Resources