Linq custom query with object properties - c#

I want know to make a query using linq, between a collection of objects
and a collection of values. In the sample code below, I make the question about it.
class USER
{
public string Name { get; set; }
}
public class MyClass
{
public MyClass()
{
List<USER> listUser = new List<USER>();
listUser.Add(new USER { Name = "A" });
listUser.Add(new USER { Name = "B" });
listUser.Add(new USER { Name = "C" });
listUser.Add(new USER { Name = "D" });
string[] arrayNames = { "A", "B" };
}
}
Using Linq how can I get all USER in listUser with them Name equals to the arrayNames values.?
The expected results wold be
//listUser[0] --> User with Name == "A"
//listUser[1] --> User with Name == "B"
Thanks in advance.

HashSet<string> names = new HashSet<string>(new string[]{ "A", "B" });
var selectedUsers = listUser.Where(user => names.Contains(user.Name));
The hashset is optional and overkill if you have only a few users but it guarantees optimal lookup performance if you have a lot of users.

listUser.Where(u => arrayNames.Contains(u.Name)).ToList();

This should so what you want, tried it in a console app. Worked a treat
var query = listUser.Where(i => arrayNames.Contains(i.Name));
foreach (var item in query)
{
Console.WriteLine(item.Name);
}
Console.ReadKey();
The key part is the arrayNames.Contains(i.Name) as this is inverse to intuition in that you specify the IEnumerable and then the linq parameter inside the contains method.

listUser = (from u in listUser where arrayNames.Contains(u.Name) select u).ToList();

Related

LINQ Where query with object list

I have a list of objects ListA with property Id and I have to make a query in a table that has a column Id and find the rows that the ids are the same. How exactly can I achieve that with a single query and not a foreach loop of listA?
Thank you for your time
foreach(var object in listA)
{
context.Table.Where(x => x.id == object.Id)....
}
Looks like you want to return all rows from the table that have an ID contained in the list of objects with the same ID. The following will achieve this. I can modify my answer to suit your need. Just let me know if you are looking for something slightly different.
void Main()
{
var listA = new List<A> { new A { Id = 1 }, new A { Id = 4 } };
var results = context.Table
.Where(t => listA.Select(l => l.Id).Contains(t.Id))
}
public class A
{
public int Id { get; set; }
}

Create a list with items from first group

I am using a list collection with two properties Name and Group.
I need to create a list collection which it will contain only elements from first group, then another list with elements from the second group and finally the third group.
My code:
public class Person
{
public string Name { get; set; }
public string Group { get; set; }
}
private void button1_Click(object sender, EventArgs e)
{
var mItems = new List<Person>();
mItems.Add(new Person{ Name="A", Group="1", });
mItems.Add(new Person { Name = "B", Group = "1", });
mItems.Add(new Person { Name = "C", Group = "2", });
mItems.Add(new Person { Name = "D", Group = "2", });
mItems.Add(new Person { Name = "E", Group = "3", });
mItems.Add(new Person { Name = "F", Group = "3", });
mItems.Add(new Person { Name = "G", Group = "1", });
}
I need to create a list with elements which are on the first group, example group "1".( i notice that this is an example, i don't not know the exactly group name in my application, it can be anything)
So my expected result is a list with A,B and G, then a second list with C,D and finally a third list with E,F. I have found code below:
var results = mItems.GroupBy(x => x.Group)
.Select(g => g.OrderBy(x => x.Group).FirstOrDefault());
But i am taking the exactly oposite result. I am taking only the first element of each group.
You need to place your FirstOrDefault() call after your Select() as it's currently inside of the select, which is causing the first of each group to be selected:
var results = mItems.GroupBy(x => x.Group)
.Select(g => g.OrderBy(x => x.Group))
.FirstOrDefault();
Likewise, if you wanted to output every group, you could just remove the FirstOrDefault() call altogether. This would return a collection of ordered collections, which you could access individually via the ElementAt() function:
var results = mItems.GroupBy(x => x.Group)
.Select(g => g.OrderBy(x => x.Group))
.ElementAt(someIndex);
Example
You can see a working example here.

LINQ select into array

I am trying to modify a LINQ query to select some properties into an array but am struggling to achieve part of it.
toRun.AddRange(entity.Properties
.Select(property => property.PrimaryField)
.Select(field => new { field, entity = entity.EntityName, table = field.Table, key = entity.EntityIdField })
I need this amending so that if a second property called SecondaryField is not null or empty string it will be added to the results of the first Select statement.
For example if entity.Properties contains:
Property { PrimaryField = "a", SecondaryField = "b" },
Property { PrimaryField = "c", SecondaryField = "" }
I would like the first Select statement to return:
{ "a", "b", "c" }
Appreciate any help thanks.
This seems to reproduce what you want: you have a class with two properties:
public class Foo
{
public string Bar { get; set; }
public string Baz { get; set; }
}
Of which you have a collection:
var foos = new List<Foo>
{
new Foo { Bar = "a", Baz = "b" },
new Foo { Bar = "c", Baz = "" },
};
And from this collection, you want to select all properties that have a non-empty value into an array.
You can do so using SelectMany():
var result = foos.SelectMany(f => new[] { f.Bar, f.Baz })
.Where(p => !string.IsNullOrWhiteSpace(p))
.ToArray();
You select a new array containing the value of both properties, then filter out the values you don't want, and turn the result into an array again.
This should be pretty simple - get both fields, use a Where to remove the null/empties and turn to an array:
var result = entity.Properties.SelectMany(p =>new[]{ p.PrimaryField,p.SecondaryField})
.Where(x => !String.IsNullOrEmpty(x))
.ToArray();
Live example: http://rextester.com/MHM61977

How to get value from IEnumerable collection using its Key?

I have IEnumerable collection like following
IEnumerable<Customer> items = new Customer[]
{
new Customer { Name = "test1", Id = 999 },
new Customer { Name = "test2", Id = 989 }
};
I want to get value using key Id
I tried like following
public int GetValue(IEnumerable<T> items,string propertyName)
{
for (int i = 0; i < items.Count(); i++)
{
(typeof(T).GetType().GetProperty(propertyName).GetValue(typeof(T), null));
// I will pass propertyName as Id and want all Id propperty values
// from items collection one by one.
}
}
If you want to retrieve a Customer name from a collection by its Id:
public string GetCustomerName(IEnumerable<Customer> customers, int id)
{
return customers.First(c => c.Id == id).Name;
}
Using LINQ you can get all customers names (values) having specific value in this way:
var valuesList = items.Where(x => x.Something == myVar).Select(v => v.Name).ToList();
For single customer name you can do this:
var singleName = items.FirstOrDefault(x => x.Id == 1)?.Name;
Obviously, the Id can be 1, 2 or any other.
Edit:
I recommend you List<Customer> instead of Customer[]
So,
var items = new List<Customer>
{
new Customer { Name = "test1", Id = 999 },
new Customer { Name = "test2", Id = 989 }
};
// I will pass propertyName as Id and want all Id propperty values
// from items collection one by one.
If I understand you correctly
public static IEnumerable<object> GetValues<T>(IEnumerable<T> items, string propertyName)
{
Type type = typeof(T);
var prop = type.GetProperty(propertyName);
foreach (var item in items)
yield return prop.GetValue(item, null);
}
Just use LINQ to achieve what you want to do. if you want to retrieve a specific value you can use where like this:
public Customer GetCustomerById(IEnumerable<Customer> items,int key)
{
return items.Where(x=>x.id==key)
.Select(x =>x.Name)
.First();
}
this will retrieve the customer who match a specific Id.
Do you want to look things up repeatedly after creating the list? If so, you might want to consider creating a dictionary to do the lookups, like so:
IEnumerable<Customer> items = new Customer[]
{
new Customer {Name = "test1", Id = 999},
new Customer {Name = "test2", Id = 989}
};
var lookup = items.ToDictionary(itemKeySelector => itemKeySelector.Id);
var result = lookup[989];
Console.WriteLine(result.Name); // Prints "test2".
I'm assuming that you don't create the collection in the first place - if you had control over creating the original collection you could use a dictionary in the first place.
private TextBox [] Collectionstextboxonpanel(Panel panel)
{
var textBoxspanel1 = panel.Controls.OfType<TextBox>(); // select controls on panle1 by type
IEnumerable<TextBox> textBoxes = textBoxspanel1; // create collection if need
TextBox[] textBoxes1 = textBoxes.ToArray(); // Array collection
return textBoxes1; // get back TextBox Collection
}

Getting a value from a ConcurrentDictionary

If I have this ConcurrentDictionary:
public class User
{
public string Context { get; set; }
public bool Owner { get; set; }
}
protected static ConcurrentDictionary<User, string> OnlineUsers = new ConcurrentDictionary<User, string>();
Does anyone know how I would get the value of Owner if I already have the value of the Context? Basically I want to do a "find" using the Context. Thanks.
Does anything stop you from using standard Linq FirstOrDefault() method like so:
var item = OnlineUsers.FirstOrDefault(kvp => kvp.Key.Context == myContext);
How obout something like
var ou = OnlineUsers.First(x => x.Key.Context == "TADA");
It sounds like you need a Dictionary<string, User> which, when given the context as a string will tell you which User it corresponds to. If you are going to need to perform this lookup several times, and there isn't a problem using the additional memory, it may be worth creating such a dictionary.
If you are only going to be doing the search once or twice, or the mappings will be changing so often that you can't keep the dictionary up to date, then you can simply do a linear search on the dictionary using a foreach loop, or using a LINQ method such as First or Where, as demonstrated in other answers.
Here you go:
ConcurrentDictionary<User, string> dict = new ConcurrentDictionary<User, string>();
dict.TryAdd(new User() { Context = "a", Ownder = false }, "aa");
dict.TryAdd(new User() { Context = "b", Ownder = false }, "bb");
dict.TryAdd(new User() { Context = "c", Ownder = true }, "cc");
dict.TryAdd(new User() { Context = "d", Ownder = false }, "dd");
IEnumerable<User> list = dict.Keys.Where(p => p.Context == "a");

Categories

Resources