Get first Item in list - c#

I am using this function to get a list of groups
public static IEnumerable<QuizGroups> GetGroups(string sectorId)
{
var Quizes = _QuizDataSource.AllQuizGroups.Where(x => x.Subtitle == sectorId);
return Quizes;
}
But this returns all, I want to return the first group in the list.
How do i change the statement to get the first group?

You can use First or FirstOfDefault and return enumerable with single element:
public static IEnumerable<QuizGroups> GetGroups(string sectorId)
{
return new[]
{
_QuizDataSource.AllQuizGroups.FirstOrDefault(x => x.Subtitle == sectorId)
};
}
Also note:
If you plan to always return one element only, consider refactoring GetGroups method to return QuizGroups only.
AllQuizGroups property may be null. Add null-check for that property.
You should consider using C# Naming Conventions.
Local variable names should be Camel Cased; so it should be: var quizes.
Property _QuizDataSource should be renamed to QuizDataSource if it is public or _quizDataSource or quizDataSource if it is private.¹
¹ — It's a heat debate whether to use _ or not for private fields, read more at: https://stackoverflow.com/questions/1630844/c-sharp-member-variables-fields-naming-convention

Try First or FirstOrDefault.
public static IEnumerable<QuizGroups> GetGroups(string sectorId)
{
var Quizes = _QuizDataSource.AllQuizGroups.FirstOrDefault(x => x.Subtitle == sectorId);
return Quizes;
}

public static QuizGroups GetGroups(string sectorId)
{
return QuizDataSource.AllQuizGroups.FirstOrDefault(
x => x.Subtitle == sectorId);
}
or add an indexer to the collection class (assuming MyQuizGroupsCollection is the type of _QuizDataSource
public class MyQuizGroupsCollection: IEnumerable<QuizGroups>
{
// other stuff
public QuizGroups this[string sectorId]
{ get { return FirstOrDefault(x => x.Subtitle == sectorId); } }
}
... then you could simply write
var Quizes = _QuizDataSource[sectorId];

Related

How to use Use List<T>.RemoveAll to simplify for loop and remove items from collection

I have this implementation below. It uses a for loop. Is there a way to eliminate the for loop and simplify the code using C# List Extensions?
public class Member
{
public string member { get; set; }
}
public class PatternMatch
{
public static List<Member> Remove()
{
var prefix = new string[] { "usa-", "o-", "a-" };
var members = new List<Member>();
members.Add(new Member { member = "a-o#b.com" });
members.Add(new Member { member = "usa-b#d.com" });
members.Add(new Member { member = "c#d.com" });
// don't use foreach since we will be modifying the collection
for (var i = members.Count - 1; i >= 0; i--)
{
foreach (var pattern in prefix)
{
if (members[i].member.StartsWith(pattern, StringComparison.InvariantCultureIgnoreCase))
{
members.RemoveAt(i);
}
}
}
return members;
}
}
RemoveAll implementation could look like this
members.RemoveAll(x => prefix.Any(p => x.member.StartsWith(p, StringComparison.InvariantCultureIgnoreCase)))
RemoveAll removes every item that matches the given Predicate<T>.
A Predicate<T> is very basically a method with a parameter of T and a return type of bool.
So the above code could be re-written as
members.RemoveAll(ConditionToRemove);
bool ConditionToRemove(Member x) => true;
The condition
x => prefix.Any(p => x.member.StartsWith(p, StringComparison.InvariantCultureIgnoreCase))
Does the following
for every T - I declared it as the variable x - it will check if their is Any entry in the list prefix that has the condition of
x.member.StartsWith(p, StringComparison.InvariantCultureIgnoreCase)
So, prefix.Any will return true if there is atleast one entry x.member starts with.
With Linq, something like this will work:
return members
.Where(m => !prefix
.Any(p => m.member.StartsWith(p, StringComparison.InvariantCultureIgnoreCase)))
.ToList();

Generic FilterClass<T> - within the class a List<predicate>(T) shall be set up, how with unknown type at runtime?

I've built a complex filter for my ICollection within my ViewModel. Now I need a similar filterfunction for a different collection and datagrid. So I guess it would suck big times if I was going to duplicate and adjust my code.
So I was going for a reusable solution.
Simple Code:
public class FilterForGrid<T>
{
public T UiModel { get; set; }
private List<Predicate<T>> criteria = new List<Predicate<T>>();
public FilterForGrid() {
// var result = typeof(T).GetProperties().ToList();
}
private bool dynamicFilter(object obj) {
T uiModel = (T)obj;
bool isIn = true;
if (criteria.Count() == 0)
return isIn;
isIn = criteria.TrueForAll(x => x(uiModel));
return isIn;
}
public void ClearFilter() {
criteria.Clear();
}
public void AddFilterArgument(string argument, string property) {
// criteria.Add(new Predicate<T>(x => x.))
}
public void FireFilter(ICollectionView toBeFilteredCollection) {
toBeFilteredCollection.Filter = dynamicFilter;
toBeFilteredCollection.Refresh();
}
}
Have a look at the method "AddFilterArgument" --> I simply want to pass the name of the property and the value over which the data shall be filtered:
public void AddFilterArgument(string argument, string property) {
criteria.Add(new Predicate<T>(x => x.property == argument))
}
But because of type inteference the property can't be found this way.
Is my attemp possible or do I have to look in another direction? If its possible please give me a clue.
Well, finally it was a much easier than expected:
Example for one of the methods
public void AddFilterPredicate(string argument, string property, OperatorsForFIlter operators) {
Predicate<T> predicate;
if (!String.IsNullOrEmpty(argument)) {
switch (operators) {
case OperatorsForFIlter.equal:
predicate = new Predicate<T>(x => x.GetType().GetProperty(property).GetValue(x, null).ToString() == argument);
break;
case OperatorsForFIlter.contains:
predicate = new Predicate<T>(x => x.GetType().GetProperty(property).GetValue(x, null).ToString().Contains(argument));
break;
default:
predicate = null;
break;
}
} else { predicate = new Predicate<T>(x => x.GetType().GetProperty(property).GetValue(x, null).ToString().Contains(argument)); }
InsertIntoCriteriaCatalogue(property, predicate);
}
This line here was exactly what I was asking for:
new Predicate<T>(x => x.GetType().GetProperty(property).GetValue(x, null).ToString().Contains(argument));
I was looking for a way to pass a name of a property as parameter and the value of the property through which the list should be filtered.
Now I can use the dynamic generic filter for all my data in every grid.

C# , make method more generic

Please look at the following method:
internal IEnumerable<Query> FilterOnUserInvolvement(IEnumerable<Query> input)
{
var user = _userManager.GetUserByADName(_user.Identity.Name);
if (_userManager.IsUserAdministrator(user) || _userManager.IsUserStaff(user))
{
return input;
}
else
{
using (var context = new QAContext())
{
var involvedQueries = context.UserInvolvement.Where(x => x.UserID == user.ID).Select(x => x.QueryID).ToList();
return input.Where(i => involvedQueries.Contains(i.ID));
}
}
}
Now this method takes IEnumerable<Query> and returns the same.
Actually the functionality of this method could be applied to any IEnumerable<Type> that holds ID.
How can I rewrite this query, using generics so it can be called with another Type that holds ID?
Just restrict your T to a type that contains ID:
internal IEnumerable<T> FilterOnUserInvolvement<T>(IEnumerable<T> input) where T : ISomeInterfaceWithId
{
}

Intersection of List of List

I have a list of lists which looks like the following
public class FilteredVM
{
public int ID { get; set; }
public string Name { get; set; }
public string Number { get; set; }
}
List<List<FilteredVM>> groupedExpressionResults = new List<List<FilteredVM>>();
I would like to Intersect the lists within this list based upon the ID's, whats the best way to tackle this?
Here's an optimized extension method:
public static HashSet<T> IntersectAll<T>(this IEnumerable<IEnumerable<T>> series, IEqualityComparer<T> equalityComparer = null)
{
if (series == null)
throw new ArgumentNullException("series");
HashSet<T> set = null;
foreach (var values in series)
{
if (set == null)
set = new HashSet<T>(values, equalityComparer ?? EqualityComparer<T>.Default);
else
set.IntersectWith(values);
}
return set ?? new HashSet<T>();
}
Use this with the following comparer:
public class FilteredVMComparer : IEqualityComparer<FilteredVM>
{
public static readonly FilteredVMComparer Instance = new FilteredVMComparer();
private FilteredVMComparer()
{
}
public bool Equals(FilteredVM x, FilteredVM y)
{
return x.ID == y.ID;
}
public int GetHashCode(FilteredVM obj)
{
return obj.ID;
}
}
Like that:
series.IntersectAll(FilteredVMComparer.Instance)
You could just write
series.Aggregate((a, b) => a.Intersect(b, FilteredVMComparer.Instance))
but it 'd be wasteful because it'd have to construct multiple sets.
Intersect will work when the type are dead equals, which in your case won't apply because you haven't implemented the GetHashCode and Equals methods, which is the best and complete way.
Thus, If you only intended to take elements that contains in both lists, than the following solution will suit you right.
Assuming list1 and list2 are type List<FilteredVM> than, The most simple way, will be doing this:
var intersectByIDs = list1.Where(elem => list2.Any(elem2 => elem2.ID == elem.ID));
If you are a fan of one-liner solutions you can use this:
List<FilteredVM> result = groupedExpressionResults.Aggregate((x, y) => x.Where(xi => y.Select(yi => yi.ID).Contains(xi.ID)).ToList());
And if you just want the IDs you can just add .Select(x => x.ID), like this:
var ids = groupedExpressionResults.Aggregate((x, y) => x.Where(xi => y.Select(yi => yi.ID).Contains(xi.ID)).ToList()).Select(x => x.ID);
Working Demo

Convert LamdaFunctions - Func<IQueryable<TD>, IOrderedQueryable<TD>> to Func<IQueryable<TE>, IOrderedQueryable<TE>>

Is there a way to convertFunc<IQueryable<TD>, IOrderedQueryable<TD>> to Func<IQueryable<TE>, IOrderedQueryable<TE>>.
Let's say I have classes Country and CountryModel.
class CountryModel
{
public string Name {get;set;}
}
class Country{
public string Name{get;set;}
}
class Repo{
public IEnumerable<TD> Get(
Func<IQueryable<TD>, IOrderedQueryable<TD>> orderBy = null)
{
IQueryable<TEntityModel> query = CurrentDbSet;
return orderBy(query).ToList(); // Convert orderBy to TE.
}
}
Using the above method I would pass CountryModel instance. But the query has to happen the entity type Country.
There might be some syntax errors. Apologies for that.
public class Repo
{
public IEnumerable<TD> Get<TD, TE>(Func<IQueryable<TD>, IOrderedQueryable<TD>> orderBy = null)
{
IQueryable<TD> query = new List<TE>().Select(t => Convert<TD, TE>(t)).AsQueryable();
return orderBy(query).AsEnumerable(); // Convert orderBy to TE.
}
public TD Convert<TD, TE>(TE input) where TD : class
{
return input as TD;
}
}
If your type TE can be casted to the type TD this should work.
You can define explicit or implicit operator in your CountryModel to convert from Country
You may find AutoMapper to be very useful.
public static class MappingExtensions
{
static MappingExtensions()
{
Mapper.CreateMap<CustomAlerts, Domain.Models.CustomAlerts>();
Mapper.CreateMap<Domain.Models.CustomAlerts, CustomAlerts>();
//add mappings for each set of objects here.
//Remember to map both ways(from x to y and from y to x)
}
//map single objects
public static TDestination Map<TSource, TDestination>(TSource item)
{
return Mapper.Map<TSource, TDestination>(item);
}
//map collections
public static IEnumerable<TDestination> Map<TSource, TDestination>(IEnumerable<TSource> item)
{
return Mapper.Map<IEnumerable<TSource>, IEnumerable<TDestination>>(item);
}
}
Then in my code, I can do the following:
var TodayDate = DateTime.Now.AddDays(1);
var Alerts = DB.CustomAlerts
.Where(x => x.EndDate >= TodayDate)
.OrderByDescending(x => x.DateCreated)
.Skip(((id - 1) * 50))
.Take(50);
return Mapping.MappingExtensions.Map<CustomAlert,Models.CustomAlert>(Alerts).ToList();
Using AutoMapper and wrapping your Func with Expression should help you:
// Initialize AutoMapper
Mapper.Initialize(cfg =>
{
cfg.CreateMap<TE, TD>();
cfg.CreateMap<TD, TE>();
});
public class Repo
{
// Wrap Func with Expression
public IEnumerable<TD> Get(Expression<Func<IQueryable<TD>, IOrderedQueryable<TD>>> orderBy = null)
{
var orderByExpr = Mapper.Map<Expression<Func<IQueryable<TE>, IOrderedQueryable<TE>>>>(orderBy);
IQueryable<TE> query = CurrentDbSet;
// Compile expression and execute as function
var items = orderByExpr.Compile()(query).ToList();
// Map back to list of TD
return Mapper.Map<IEnumerable<TD>>(items);
}
}

Categories