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

Delphi 7 not generating COM classes when importing Type Library
How can we create different mapping for same entity in automapper
How to implement an MVC global action
How to get the Hololens Locatable Camera view and projection matrices out of the WinRT Windows.Media API
C# ,How to I make bindable string picker?
Ignoring exceptions when using c# selenium webdriverWait wait.untill() function
File download from C# not working, I can see in the browser response from the API
How to invoke async methods in Hangfire?
asp.net web application: Invalid postback or callback argument error on button click
C# Refactoring methods with same code except different function calls
getting data between two Longdates c# MS access database
ASP.NET Fileupload
WPF Binding to custom DependencyProperty - IsChecked is sometimes opposite value of property
data annotation - to check that date is always in future and 1st
Deserialise JSON Object [duplicate]
Proper way of closing Oracle table update - C# . NET

Categories

HOME
ssms
msbuild
indexing
sql-server-2014
qemu
snappy
arcgis
azure-resource-manager
perl6
handlebars.js
wavefront
webpack-dev-server
coding-style
google-app-maker
opengrok
webseal
tag-cloud
google-calendar-api3
geography
loader
hl7-fhir
ejb-3.1
mattermost
beaker-notebook
ecmascript-2017
ithit-webdav-server
aws-certificate-manager
core-animation
knapsack-problem
windows-mobile
resx
bytebuffer
spock
2checkout
ios9
mplab
fastadapter
webmock
tunnel
wit-ai
cache-control
leaderboard
campaign-monitor
framebuffer
lfe
idea-plugin
google-cloud-powershell
uitextview
taiga
geminabox
react.rb
openidm
ajv
android-vectordrawable
printer-control-language
zedgraph
networkstream
tinybox2
csc
qtruby
falcon
angularfire
shtml
newlib
imageicon
event-tracking
self-join
updating
bungeecord
jad
mri
mathics
crystal-reports-7
report-builder2.0
jsonschema2pojo
pytz
disabled-control
msdropdown
sendy
farpoint-spread
internet-radio
nvcc
google-oauth-java-client
8-puzzle
kohana-orm
violation
source-depot
android-library
tasklist
idtabs
towerjs
mismatch
functional-specifications
mass-emails
lgpl
text-manipulation
system-analysis
opengl-to-opengles
software-update
cons
weak-typing

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