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

How can i load item from a listBox as file and show the file content?
Validation for Navigation Properties in MVC (4) and EF (4)
Why System.Numerics.BigInteger cannot be used in a portable library targeting .Net 4
How to create WinRT C# dll api
Code Contract to prevent duplicates on list
Create objects based on input
Xceed Datagrid ExportToExcel .xml/.xls/.xlsx format
Excel values to Range of variable columns
Dynamic button click event in webkit browser using C#
Adding an ellipse to mouse position?
Accessing members of the Main class from another class
How to create a copy of items in database without breaking FK constraints?
How to refactor procedural code?
How to combine these two LINQ statements?
WPF ElementHost in WinForms not receiving mouse clicks
Best approach for delayed time password?

Categories

HOME
oauth-2.0
pact
autohotkey
internet-explorer
model-view-controller
grizzly
stanford-nlp
alasql
ide
bigtable
mifare
hiveql
gnuradio
meson-build
open-search-server
vsixmanifest
box-api
elastalert
ldap-query
jetbrains
console-application
sha1
infopath
draw2d
ampscript
email-client
aws-iot
aws-certificate-manager
symlink
android-cursorloader
resx
exacttarget
ios-autolayout
directions
cocoa-scripting
azure-storage-files
scip
julia-jump
keychain
socketcluster
libzip
django-cors-headers
spring-webflow-2
google-chrome-storage
jcs
audio-fingerprinting
android-vectordrawable
multi-select
android-tabs
dbi
normalisation
supervised-learning
razorengine
archiva
firefox-os
sqldataadapter
yfiles
lytro
cloud-storage
dpkt
web-standards
targetprocess
mergecursor
valdr-bean-validation
copy-on-write
mri
mathics
applinks
report-builder2.0
parallel-port
rpt
django-tests
pthreads-win32
mongoid4
objectdatasource
infinity.js
select2-rails
system.transactions
microsoft-speech-platform
linqdatasource
correctness
android-memory
aspmenu-control
flatten
erlide
mvcmailer
inserthtml
wdm
httppostedfilebase
session-hijacking
functional-specifications
netduino
cpack
onunload
mediastreamsource
oaw
database-agnostic
konsole
scala-designer

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
Mobile App
Mobile App
Mobile App