Linq - Select rows which are on lists - c#

I have got table "Actions" which has fields like Player, Game, Type - ale connected with other tables. I have also two Lists in my c# code:
List<Player> playersForStats
List<Game> gamesForStats
Now i want to select a rows from Actions which (field)Players are in list playersForStats and (field)Game are in list gamesForStats. How can I make it using linq? I have to use inner join or something else?

Something like this should work if your object has proper equals method:
var oActions = ..
var oData = oActions.Where(c=> c.Players.TrueForAll(p => playersForStats.Contains(p)) && gamesForStats.Contains(c.Game));
Assuming that c.Players is List And c.Game is Field.

I'd assume your action list named as actions:
actions.Where(x=>playersForStats.Contains(x.Player) && gamesForStats.Contains(x=>x.Game));
In fact just need to search if playersForStats and gamesForStats contains related action's player and game.

Something like this :
class Program
{
static void Main(string[] args)
{
List<Action> actions = new List<Action>();
List<Game> gamesForStats = new List<Game>();
List<Player> playersForStats = new List<Player>();
List<Action> result = (from oAction in actions
join game in gamesForStats on oAction.Game equals game.GameName
join player in playersForStats on oAction.Player equals player.PlayerName
select oAction).ToList();
Console.ReadLine();
}
}
public class Player
{
public string PlayerName { get; set; }
}
public class Game
{
public string GameName { get; set; }
}
public class Action
{
public string Player { get; set; }
public string Game { get; set; }
public string Type { get; set; }
}

Related

Join the data of different Lists present in different classes

public class EmpManagement
{
public List<Employee> empList = new List<Employee>();
//Method for adding new employee
public void AddEmp(Employee emp)
{
empList.Add(emp);
}
public void displayEmp(Employee emp)
{
Console.WriteLine("[" + emp.Empname + "]");
}
//Method for viewing all employees
public void ShowEmp()
{
foreach (var e in empList)
{
displayEmp(e);
}
}
}
public class Role
{
public string RoleName { get; set; }
public Role(string roleName)
{
RoleName = roleName;
}
}
public class RoleManagement
{
public List<Role> RoleList = new List<Role>();
//Method for adding roles
public void RoleAdd(Role role)
{
RoleList.Add(role);
}
//Method for viewing all roles
public void displayRole()
{
foreach (var e in RoleList)
{
Console.WriteLine(e.RoleName);
}
}
}
Join the above two lists in a different class
How can i add below two Lists into another list of different class
I am facing a problem while using a interface in one class and extending into the new class
I am also unable to use contains keyword, the compiler says that the name does not exist in current context
First, declare two lists and join these two in another list.
Please check the example below
List <string> list1 = new List <string>(){"L1L1","L1L2","L1L3"};
List <string> list2 = new List <string>(){"L2L1","L2L2","L2L3"};
List<string> joinList = list1.Join(list2);
Please see another example which is given below.
public class Role
{
public string name { get; set; }
}
public class Role2
{
public string name { get; set; }
}
public class RoleManagement
{
public List<Role> r1 = new List<Role>();
public List<Role> r2 = new List<Role>();
List<string> joinList2 = r1.Join(r2);
}
You cannot join two lists of different types into a single list. But you could still take casting into consideration, and cast the two data types into a single data type and then join the two lists into a single list.
for more information, you could refer to the following :
https://linuxhint.com/csharp-combine-two-lists/#:~:text=We%20will%20demonstrate%20an%20example,cs%E2%80%9D%20extension.

C# Filter List of objects by string

I have a list of objects. Each object has n properties. I have a another list with m [1..n] property names.
Two questions:
How do I filter the list of objects by checking if one of the properties in the other list contains a string?
How do I filter the list of objects by checking if ANY property contains a string?
Here is the object class:
public class MyModel
{
public string POne { get; set; }
public string PTwo { get; set; }
public string PThree { get; set; }
}
In pseudocode in would be something like:
New List filtered
Foreach object o in myObjectList
If o.POne, o.PTwo or o.PThree contains string "test"
filtered.Add(o)
Else
Next
I tried to adapt the code from this post, but could not get a working.
Another thought would be to create a nested list with all property values. In that scenario I get the filtering working with the following line:
List<List<string>> filtered = testList.Where(q => q.Any(a => a.Contains(testString))).ToList();
But isn't that creating a lot of overhead by creating all those extra lists?
Performance is a concern for me.
Make your Class responsible for determing if it matches or not via a method
public class MyModel
{
public string POne { get; set; }
public string PTwo { get; set; }
public string PThree { get; set; }
public bool DoesMatch(string tomatch)
{
return POne.Equals(tomatch) ||
PTwo.Equals(tomatch) ||
PThree.Equals(tomatch);
}
}
Then you can do this
var filtered = testList.Where(q => q.DoesMatch("string to check"));

How to bind data to Data-grid-view using List with extended objects

I try to bind List<Member> to DataGrid but I have no idea how to do it.
I have two classes:
public class Member
{
public int id { get; set; }
public string name { get; set; }
public double salary { get; set; }
}
public class Player : Member
{
public double bonus { get; set; }
}
List<Member> contains both Member and Player objects. I know I should cast a Member object to a Player where it is needed. I do not know how to do it within one list.
If I bind List <Member>, it only displays Member variables and their values without additional fields if the object is, in fact, a Player. Should I iterate it and how?
This is how I collect them now:
List<Member> list = db.Members.ToList();
dataGridView1.DataSource = list;
Return is:
Member
Player
Expectation:
You need to give one type if you use List collection, so you can try to let List<Member> convert to List<Player>
from your expect result bonus property can be double?
public class Member
{
public int id { get; set; }
public string name { get; set; }
public double salary { get; set; }
}
public class Player : Member
{
public double? bonus { get; set; }
}
Binding on the girdview by Player list.
List<Player> list = db.Members.Select(x => {
Player p = x as Player;
if (p != null)
return p;
return new Player()
{
id = x.id,
name = x.name,
salary = x.salary
};
});
dataGridView1.DataSource = list;
Unless you add the columns explicitly (eg. in designer), the columns are auto-created from the element type of the bound list. As this is Member in your example the grid will have no Salary column. So maybe you can create a list of some transformed class created like this:
public class MemberViewModel
{
private Member member;
public MemberViewModel(Member member) => this.member = member;
public int Id => member.id;
public string Name => member.name;
public double Salary => member.salary;
public double? Bonus => member is Player player ? player.bonus : default(double?);
}
And then:
dataGridView1.DataSource = myOriginalMemberList.Select(member => new MemberViewModel(member)).ToList();
You must retrieve data from Player instead of Member
List<Player> list = db.Players.ToList();
You can try to cast your Member to a Player and if it is a success then you can add that value to the grid:
foreach(var record in list)
{
var player = record as Player; // try to cast your record to Player
if (player != null)
{
// if it is a player do something with it
...
}
}
Hopefully this will give you the idea how you can manage to case and add Players to the grid.

Use Linq to return a new object from a nested class

I have a list of elements that contain another list.
public class SiloNode
{
public string Key { get; private set; }
public string Url { get; private set; }
public List<NodeQuery> Queries { get; private set; }
}
public class NodeQuery
{
public string Query { get; private set; }
public int Seq { get; private set; }
}
I need to produce a new list containing all queries, with the corresponding parent url.
An example would be:
https://www.bbc.co.uk, How old is the BBC?
https://www.bbc.co.uk, Where can I find a guide to BBC channels?
https://www.bbc.co.uk, How is the BBC funded?
https://www.channel4.com, More queries about channel 4 ...
The output should be in the form of class LinkMeta.
public class LinkMeta
{
public LinkMeta(string url, string text)
{
Url = url;
Text = text;
}
public string Text { get; private set; }
public string Url { get; private set; }
}
The complete list is contained in: root.Children.
The query below gives me all Query elements but I can't get back to Url.
var filtered = root.Children.SelectMany(x => x.Queries.Select(y => y.Query));
You can achieve it with the below linq.
var filtered = (from snode in root
from qry in snode.Queries
select new LinkMeta(snode.Url, qry.Query)).ToList();
It will return List of LinkMeta. Hope it helps.
Lambda expressions have the same scope as the nested block. This means that the nested lambda expression still has access to the variable 'x'. So, you should be able to do the following:
var filtered = root.SelectMany(x => x.Children.Queries.Select(y => new LinkMeta(x.Url, y.Query));

C# merging two or more objects

Hi I want to merge two objects together so that i can use the merged object to do something else.it's actually a simple airport program, i have "Route" and ""Flight" and if i want to add getting ticket i need each flight to be on a route if you know what i mean.but notice that i don't want to compare them.and i have an array of objects for each of them if it helps.
IRoute R = new LocalRoute(port, destination, routenum);
IFlight F = new LocalFlight(time, date,capacity);
I would give the Flight objects a Route property. This makes more sense to me than creating a class to hold both a Flight and a Route, since in the real world a flight should know which route it has to take.
For example:
public class Route {
public int Number { get; private set; }
public string Port { get; private set; }
public string Destination { get; private set; }
public Route(int number, string port, string destination) {
Number = number;
Port = port;
Destination = destination;
}
}
public class Flight {
public DateTime DepartureTime { get; private set; }
public int Capacity { get; private set; }
public Route Route { get; private set; }
public Flight(DateTime departureTime, int capacity, Route route) {
DepartureTime = departureTime;
Capacity = capacity;
Route = route;
}
}
Then you can have a list of possible routes and a list of flights, each of which has a reference to a route.
Would this do what you are looking for?
public class FlightDetails
{
IRoute Route {get;set}
IFlight Flight {get;set;}
}
For a more clear picture you can do something like this
public class FlightDetails
{
IRoute Route {get;set}
IFlight Flight {get;set;}
public FlightDetails(IRoute r,IFlight f)
{
this.Route = r;this.Flight = f;
}
}
IRoute R = new LocalRoute(port, destination, routenum);
IFlight F = new LocalFlight(time, date,capacity);
FlightDetails Fd = new FlightDetails(R,F);

Categories