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

DataView LIKE function on Integer value
Accessing and changing structs as property vs as field
Characters between two exact characters [closed]
Connecting Java/Android to .NET webservice [closed]
Implementing MaintainScrollPositionOnPostBack with a WebUserControl
While loop warns of always true since value of type 'int' is never equal to 'null' of type 'int'
Is this how to write a Thread-Safe IComparable?
combobox focus on beginning of text after selection
Is it possible to store, or pre-define a LINQ query for re-use?
Appending variable in for loop to mvc4 razor helper
Using Web API DelegatingHandler in MVC
checking if gridview is empty using c#
WCF : Making methods in DataContract object accessible to web service clients
Host ASPX file next to WCF Service
RemotingConfiguration lock my file, how to use log4net's RemotingAppender?
How to play .mid Sound in resources using windows media player in c#

Categories

HOME
reactjs
apache-storm
python-requests
azure-database-mysql
watson-iot
snmp
perl6
sugarcrm
yuv
foreach
liquidsoap
schema
install
digital
jcodemodel
wowza
mamp
adroitlogic
drush
aggregate
webseal
web-testing
web-worker
xforms
glibc
minimagick
combinations
infinite-loop
proof-general
windows-10-mobile
ios9
textview
ibm-bpm
contextmenustrip
node-soap
mootools
asp.net-webhooks
hippocms
mapquest
office-interop
jvisualvm
ionic2-select
spring-cloud-bus
noise
jcs
sp
suitesparse
msiexec
directinput
zsh-completion
easy68k
scikit-image
consolidation
alfred
dimensionality-reduction
instaparse
kik
archiva
jmap
android-progressbar
custom-build-step
cascading
encode
android-facebook
android-togglebutton
syncano
xml-simple
data-representation
avd
wingdb
qxorm
formbuilder
cocos2d-x-2.x
powershell-v1.0
switchpreference
twitter-finagle
slimscroll
.net-reflector
facebook-likebox
mysql-error-1146
caroufredsel
extensibility
wpd
proj4
symbian3
exi
codeigniter-form-helper
junction-table
nsautoreleasepool
ntdll
webpage-screenshot
filedialog
winrt-async
github-archive
dancer
optimistic-concurrency
parsec
unordered-set
cherokee
isgl3d
jexcelapi
xcdatamodel
virtual-destructor
arraycollection
chars
oaw
p4.net
file-storage

Resources

Encrypt Message



code
soft
python
ios
c
html
jquery
cloud
mobile