c#


Linq: Filter list of type A based on an object of type A?


I have a List of objects of type Foo, and another instance of an object of type Foo. I would like to use linq to filter the list based on the non-null properties of the instance.
class Foo {
public int ID;
public string Description;
public long Location;
}
Foo fooFilter = new Foo() {
ID = null,
Description = null,
Location = 1
}
List<Foo> fooList = new List<Foo>();
fooList.Add(new Foo(){ID = 1, Description = "one", Location = 1});
fooList.Add(new Foo(){ID = 2, Description = "two", Location = 0});
fooList.Add(new Foo(){ID = 3, Description = "three", Location = 1});
List<Foo> filteredFooList = fooList.Where(???);
I want to somehow use fooFilter to query fooList and fill filteredFooList with:
[
{ID = 1, Description = "one", Location = 1},
{ID = 3, Description = "three", Location = 1}
]
EDIT:
I was trying to be brief to make the question more clear, but I might have left of important information. In my actual program, List<Foo> is a large result from a database (over 40k entries). I'm trying to make a controller method (MVC) which can take any combination of parameters that would match the field names of an entity framework object. So <Foo> is a EF record type. So I'm trying to avoid having to explicitly list all the (15 or so) fields that can be filtered on in the controller:
public class Home : Controller
{
public ActionResult FilteredFooList(int ID, string Description, long Location, etc, etc, etc)
{
}
}
And do something more like:
public class Home : Controller
{
public ActionResult FilteredFooList(Foo filterObj)
{
}
}
Maybe this isn't possible or a good idea?
If you only want to filter out non instanciated properties, you don't need a filter.
class Foo
{
public int ID;
public string Description;
public long Location;
public bool IsInstanciated()
{
return this.ID != default(int) && this.Description != default(string) && this.Location != default(long);
}
}
List<Foo> filteredFooList = fooList.Where(f => f.IsInstanciated());
If you really need to use that instanciated class as a filter, I'd suggest you to use IEquatable<T>
class Foo : IEquatable<Foo>
{
public int ID;
public string Description;
public long Location;
public bool Equals(Foo other)
{
// Whatever your logic is
return this.Description == other.Description && this.ID == other.ID && this.Location == other.Location;
}
}
List<Foo> filteredFooList = fooList.Where(f => !f.Equals(fooFilter));
Assuming you can change your value types to be nullable:
class Foo {
public int? ID;
public string Description;
public long? Location;
}
Then you can use some extensions:
public static class Ext {
public static bool EqualOrNull<T>(this T? value, T? filter) where T : struct, IComparable {
return (filter == null) || (value.Value.CompareTo(filter.Value) == 0);
}
public static bool EqualOrNull<T>(this T value, T filter) where T : class, IComparable {
return (filter == null) || (value.CompareTo(filter) == 0);
}
}
To do this:
var filteredFooList = fooList.Where(f => f.ID.EqualOrNull(fooFilter.ID) && f.Description.EqualOrNull(fooFilter.Description) && f.Location.EqualOrNull(fooFilter.Location));
If you wanted something truly generic (e.g. not dependent on knowing the field names) you would need to step into the world of Reflection.
By looking at your expected output, it appears that you want to filter fooList so that you get all items that have the same Location as your fooFilter object. If that's what you're asking, you can do this:
List<Foo> filteredFooList = fooList.Where(item => item.Location == fooFilter.Location);
Don't paint yourself into a corner by adding unnecessary properties to your data objects, they should stay data objects. You're effectively trying to build a dynamic query where you want to conditionally filter by a list of conditions. There are patterns to do this.
Start with a base query, then determine if you want to filter by one of the properties. Do the same with the rest of the other properties. By the time you reach the end, you could then just gather the results.
var filter = new Foo
{
ID = null,
Description = null,
Location = 1,
};
var data = new List<Foo>
{
new Foo { ID = 1, Description = "one", Location = 1 },
new Foo { ID = 2, Description = "two", Location = 0 },
new Foo { ID = 3, Description = "three", Location = 1 },
};
var query = data.AsEnumerable();
if (filter.ID != null)
query = query.Where(x => x.ID == filter.ID);
if (filter.Description != null)
query = query.Where(x => x.Description == filter.Description);
if (filter.Location != null)
query = query.Where(x => x.Location == filter.Location);
var result = query.ToList();
This assumes that ID and Location are actually nullable just like your example implies.
public class Foo
{
public int? ID { get; set; }
public string Description { get; set; }
public long? Location { get; set; }
}

Related Links

Webrequest looks identical but won't log in?
C# checkbox event in asp.net mvc view not inside form
MonoGame porting to linux
Add to usings doesn't appear as resolve option in Visual Studio 2015
Outlined font effect for text in WPF
How to draw tensor visualization on a 2D grid
NullReferenceException C# [duplicate]
c# How do I detect if a line (painted/drawn on a form) has been clicked on when using winforms?
Parse the css content in C#
Stripe.net - Try to charge on behalf
Running oracle script in c#
How to calculate Sum of Peak and Offpeak hours in List<TimeSpan>
MySQL preprocessor optimization
Two methods with the same signature except for optional parameter
Set value of an object based on combobox selection (xaml / c#, uwp)
How to add space between two lines of a string in C#?

Categories

HOME
reactjs
itunesconnect
qemu
ldap
kendo-asp.net-mvc
scapy
promotions
ethereum
theory
aspectj
email-attachments
swift3.1
versioning
geography
minimagick
gnu-screen
gsuite
pydub
uibarbuttonitem
custom-fields
openoffice-impress
multilanguage
rtos
n1ql
wunderground
intersection
javafxports
kofax
lighting
strategy-pattern
kepserverex
rtsp
stencyl
icu
binary-decision-diagram
qt-quick
amazon-rds-aurora
codepen
spring-webflow-2
e4
totalview
reloaddata
chain
dynatable
spring-cloud-aws
sqlproj
sbt-proguard
jde
pebble-js
abstract
hana-sql-script
gtkwave
jcomponent
commercetools
recode
edgar
notice
eaaccessory
nmock
stereotype
ultraedit
gmaps4jsf
chrome-mobile
crtdbg.h
quickfixn
xcode5
jsonmodel
xmlserializer
gnip
xpand
sqldatasource
class-library
git-subtree
xcode6.1-gm-seed
svg-android
misfire-instruction
infomaker
source-depot
codeigniter-form-helper
gwt2
simplemembership
configurationsection
eeprom
joomla1.7
cgaffinetransform
vectorwise
execjs
service-layer
viewdata
simultaneous
database-agnostic
helios
morfik
authkit

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html