Get all values for a certain property name in linq? - c#

Is there a way to get all values for a certain key in linq?
Here is my collection
[PId, Pname, EnviornementName]
So I have a collection of this type, Looking for a more generic approach, where i could check the property name and do a select. Something like,
myCollection.SelectMany(item => item).Where(item==propertyName)
how can i do this?

To get an array of named property values try
var pName = "PId";
var values = myCollection
.Select(x => x.GetType().GetProperty(pName).GetValue(x, null))
.ToArray();

There are several ways to do it, for example:
var IDs = from o in myCollection
select new { o.PId };
or
var IDs = myCollection.Select(o => o.PId);
I suggest that you start with some linq tutorial: http://www.tutorialspoint.com/linq/

using System.Linq;
MyCollection.Select(x => x.Pid).ToArray();
Or to get unique values
MyCollection.Select(x => x.Pid).Distinct().ToArray();
Or better yet, a sorted array of unique values
MyCollection
.OrderBy(x => x.Pid)
.Select(x = x.Pid)
.Distinct()
.ToArray();

Related

How to compare list anonymous type to another list

I am trying to use Except to compare two list but one is an anonymous type.
For Example:
var list1 = customer.Select(x => new { x.ID, x.Name }).ToList();
var list2 = existcustomer.Select(x => x.ID).ToList();
And I trying to compare two list IDs and return a list of list one name.
My code:
var checkIfCustomerIdNotExist = list1.Where(x => x.ID.ToList().Except(list2)).Select(x => x.Name).ToList();
I am wondering if there is any workaround.
I'd advise using a dictionary instead of a List
//create a dictionary of ID to name
var customerDict = customer.ToDictionary(x => x.ID, x => x.Name);
//get your list to compare to
var list2 = existcustomer.Select(x => x.ID).ToList();
//get all entries where the id is not in the second list, and then grab the names
var newNames = customerDict.Where(x => !list2.Contains(x.Key)).Select(x => x.Value).ToList();
In general it's good to think about what data structure suits your data the best. In your case list1 contains a list of tuple where ID needs to be used to find Name - using a data structure more suited to that (A dictionary) makes solving your problem much easier and cleaner
Note, the solution assumes ID is unique, if there are duplicate IDs with different names you might need a Dictionary<string, List< string >> instead of just a Dictionary<string,string> - but that would probably require more than just a single line of linq, code would be fairly similar though

Replace the list items with specific characters using lambda

This will give me the list of string having "WIGS_AUTH_" in each item. Now I want to remove this part from the list items in the same expression. Or any better way to achieve this?
you can add another Select at the end
List<PermissionDto> ans = result
.Where(x => x.Contains("WIGS_AUTH_"))
.Select(x => new PermissionDto { Name = x.Replace("WIGS_AUTH_", "") })
.ToList();
you can try something like this:
result.Where(x => x.Contains("WIGS_AUTH")).Select(x => new Permision() { Name=x.Replace("WIGS_AUTH","") }).ToList();
First its filtering the result and taking items containing "WING_AUT"
now it is creating new object of PermissionDto and set name property without "WIGS_AUTH"
adding new object to list and returning back

LINQ Syntax for Selecting a Parameter to Be Copied

I have a some code to sort my collection in linq in C#. I want it to group by the houseName to sum over the volumes, order that collection, but also pass a third parameter, pctVol, to the new sorted collection. What am I doing wrong? I know that the problem lies in the pctVol = group.Selecct(item => item.pctVol) line.
var inBetween = this.GroupBy(item => item.houseName)
.Select(group =>
new DataItem
{
houseName = group.Key,
VOLUME = group.Sum(item => item.VOLUME),
pctVol = group.Select(item => item.pctVol)
})
.ToList();
ObservableCollection<DataItem> objSort = new ObservableCollection<DataItem>(inBetween.OrderBy(DataItem =>
DataItem.VOLUME));
return objSort;
What kind of value do you want pctVol to have? With that code, it looks like DataItem.pctVol will be an IEnumerable containing all the pctVol values in that group.
If you want a single value, and all the pctVol values in each group are guaranteed to be the same, then you could just take the value from the first element, like this: pctVol = group.First().pctVol

best way to receive a list of objects from list of KeyValuePair?

I have a list of KeyValuePairs and I want to filter it based on the key value so eventually I will get a list of values which is filtered (meaning - will not contain all the values that were in the original list).
I guess maybe the best way is some form of Lambda expression but I am not sure how to achieve it.
Thanks,
Alon
Try this:
var values = list.Where(x => x.Key == "whatever").Select(x => x.Value);
This will give you a filtered list of the values only.
Obviously you can change the way you filter your keys.
Use the following:
var filteredList = list.Where(x => x.Key == "Key");
What you're looking for some combination of LINQ extension methods (which depends on what you're exactly trying to do).
For example if I had a List of fruits to their colors and wanted to get a collection of which fruits are red, I would do something like:
var fruits = new List<KeyValuePair<string,string>>() {
new KeyValuePair<string,string>("Apple", "Green"),
new KeyValuePair<string,string>("Orange", "Orange"),
new KeyValuePair<string,string>("Strawberry", "Red"),
new KeyValuePair<string,string>("Cherry", "Red")
};
var redFruits = fruits.Where(kvp => kvp.Value == "Red").Select(kvp => kvp.Key);
// this would result in a IEnumberable<string> { "Strawberry", "Cherry" }

LINQ using C# question

I have a List<T> that contains some user defined class data.
I want to find the unique instances of a combination of 2 data fields.
For example, if the entries contain the fields Name and Age, I want the unique cases of the Name and Age combination, e.g. Darren 32, should only be retrieved once, even if it is in the list multiple times.
Can this be achieved with LINQ?
Thanks.
You need to extract only these data fields and make them unique:
var result = list
.Select(x => new { Age = a.Age, Name = x.Name})
.Distinct();
This creates a IEnumerable of a anonymous type which contains a Age and Name property.
If you need to find the items behind the unique data, you need GroupBy. This will provide the list with the single items behind each group.
var result = list
.GroupBy(x => new { Age = a.Age, Name = x.Name});
foreach (var uniqueItem in result )
{
var age = uniqueItem.Key.Age;
var name = uniqueItem.Key.Name;
foreach (var item in uniqueItem)
{
//item is a single item which is part of the group
}
}
myList.Select(l => new { l.Name, l.Age })
.Distinct()
.ToDictionary(x => x.Name, x => x.Age)
You'll have to write your own equality comparer, and use Linq's Distinct function.
Have a look at the Distinct extension method
Easy:
var people = new List<Person>();
// code to populate people
var uniqueNameAges =
(from p in people
select new { p.Name, p.Age }).Distinct();
And then to a dictionary:
var dictionary =
uniqueNameAges
.ToDictionary(x => x.Name, x => x.Age);
Or to a lookup (very much like Dictionary<string, IEnumerable<int>> in this case):
var lookup =
uniqueNameAges
.ToLookup(x => x.Name, x => x.Age);
If you then have people named "John" with distinct ages then you could access them like so:
IEnumerable<int> ages = lookup["John"];

Categories