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

Efforts in iteration - FizzBuzz
Importing C++ DLL into C# Smart Device Application
C# XML Serialization/DeSerialization [closed]
C# WPF delete checked items in treeview
Creating overload for String.GetHashCode() to return same value in x86 and x64 environments
Ordered list of C# properties, for common operations?
How do I compile an AVI file from a bunch of bitmaps in C# ASP.NET?
Unit test a controller attribute which depends on the requested URL parameters (ASP.NET MVC)
How could I have one column store an arbitrary number of “users”
How to set values in x axis MSChart using C#
Problem with RegEx OR operator in C#
WPF binding where value = X
WPF MVVM CanExecute method implementation problem
Exposing delegate through properties in C#
MVC, ORM, and data access patterns
C# DragDrop object with children results in System.InvalidOperationException

Categories

HOME
internet-explorer
process
casting
skypedeveloper
stdout
osx-yosemite
wowza
fastreport
logstash-configuration
ibatis
alert
caldav
android-navigation-drawer
combinations
smali
handle
apdu
ppp
scalatest
ibm-bpm
snapkit
eclipse-jdt
rtos
traitsui
angularjs-resource
intersection
mkdir
flex3
gstreamer-1.0
blueimp
file-conversion
mixed-models
vertical-alignment
collation
text-extraction
bootstrap-carousel
android-doze-and-standby
reqif
opos
extjs3
android-vectordrawable
senti-wordnet
tsc
acceleo
pyautogui
therubyracer
fileopendialog
blackberry-webworks
glade
easy68k
papyrus
cosign-api
nd4j
sqldataadapter
videoview
github-for-mac
ios8-share-extension
windows-kernel
page-flipping
photogrammetry
stderr
accpac
nsnotificationcenter
episerver-7
sendy
smartxls
fastcgi-mono-server
nativequery
node-amqp
google-mirror-api
misfire-instruction
caroufredsel
android-library
symbian3
wordbreaker
spawn
biztalk-deployment
microsoft-speech-platform
php-gettext
eeprom
isgl3d
llblgen
mediastreamsource
silverlight-2.0
dgml
web-widget
manuals
qlibrary
high-load
cons
moores-law

Resources

Encrypt Message



code
soft
python
ios
c
html
jquery
cloud
mobile