This below is my code and I want to write a linq query for this three list (Dictionaryfilter,collectionfilter,reffrencefilter) this as are mmy list and want to add when item is selected then add into a SelectedIdList ,Using Linq in c#
SelectedIdList = new List<long>();
foreach (var item in DictionariesFilter)
{
if (item.IsSelected)
{
SelectedIdList.Add(item.DictionaryId);
}
}
foreach (var item in CollectionsFilter)
{
if (item.IsSelected)
{
SelectedIdList.Add(item.DictionaryId);
}
}
foreach (var item in RefrencesFilter)
{
if (item.IsSelected)
{
SelectedIdList.Add(item.DictionaryId);
}
}
It could look something like:
SelectedIdList.AddRange(
DictionariesFilter.Where(x=>x.IsSelected).Select(x=>(long)x.DictionaryId)
);
SelectedIdList.AddRange(
CollectionsFilter.Where(x=>x.IsSelected).Select(x=>(long)x.DictionaryId)
);
SelectedIdList.AddRange(
RefrencesFilter.Where(x=>x.IsSelected).Select(x=>(long)x.DictionaryId)
);
You can do like this.
var results1 = from item in DictionariesFilter
where item.IsSelected
select item.DictionaryId;
selectedList.Add(results1);
and in similar way you could do for the rest of loops.
You could try, if possible:
public interface IFilter
{
bool IsSelected { get; }
int DictionaryId { get; }
}
SelectedIdList = new IFilter[] { DictionariesFilter, CollectionsFilter, ReferencesFilter}
.SelectMany(dic => dic.Where(x => x.IsSelected).Select(x = > (long)x.DictionaryId) )
.ToList();
One way of doing this is to simply use Where and Concat.
SelectedIdList = DictionariesFilter.Where(x => x.IsSelected).Select(x => (long)x.DictionaryId)
.Concat(CollectionsFilter.Where(x => x.IsSelected).Select(x => (long)x.DictionaryId))
.Concat(RefrencesFilter.Where(x => x.IsSelected).Select(x => (long)x.DictionaryId))
.ToList();
If they have a common interface it could be simplified.
public interface IFilter
{
bool IsSelected { get; }
long DictionaryId { get; }
}
SelectedIdList = DictionariesFilter
.Concat(CollectionsFilter)
.Concat(RefrencesFilter)
.Where(x => x.IsSelected)
.Select(x => x.DictionaryId)
.ToList();
Related
I'm trying to reduce code, how can I use linq query to reduce number of lines in this method?
private IEnumerable<OutputResponse> GetOutput(IEnumerable<Item> items)
{
foreach (var item in items)
{
var products= item.Products?.Select(x => new ProductName(x));
if (products!= null)
{
foreach (var product in products)
{
yield return new OutputResponse
{
Name = product.Name,
Description = product.Description
};
}
}
}
}
You can try
private IEnumerable<OutputResponse> GetOutput(IEnumerable<Item> items)
{
var results=items.SelectMany(item=>item.Products ?? Enumerable.Empty<Product>())
.Select(p=>new ProductName(p))
.Select(pn=>new OutputResponse {
Name=pn.Name,
Description=pn.Description
});
return results;
}
or
private IEnumerable<OutputResponse> GetOutput(IEnumerable<Item> items)
{
var results =from item in items
from p in item.Products ?? Enumerable.Empty<Product>()
let pn=new ProductName(p)
select new OutputResponse {
Name=pn.Name,
Description=pn.Description
};
return results;
}
As everyone else mentioned though, that ProductName seems to have no purpose.
Writing those queries requires some guessing and assumptions though, eg what each class contains, and what Products contains. I assume the classes involved looks something like this :
class OutputResponse
{
public string Name;
public string Description;
}
class ProductName
{
public string Name;
public string Description;
public ProductName(Product x)=>(Name,Description)=(x.Name,x.Description);
}
class Product
{
public string Name;
public string Description;
}
class Item
{
public List<Product> Products;
}
items.SelectMany(x => x.Products ?? Array.Empty<Product>).
.Select(x =>
{
var product = new ProductName(x);
return new OutputResponse
{
Name = product.Name,
Description = product.Description
};
}
But try to get rid of this ProductName conversion.
If it's really not possible you can also use this:
items.SelectMany(x => x.Products ?? Array.Empty<Product>).
.Select(x => new ProductName(x))
.Select(product =>
new OutputResponse
{
Name = product.Name,
Description = product.Description
});
Depends on how far you want to take it really in my opinion:
private IEnumerable<OutputResponse> GetOutput(IEnumerable<Item> items)
{
var products = items
.SelectMany(x => x.Products
.Where(p => p != null)
.Select(p => new ProductName(p)));
foreach (var product in products)
{
yield return new OutputResponse
{
Name = product.Name,
Description = product.Description
};
}
}
Here you can see that I've encompassed the logic in a linq statement.
I am looping through the items to get the products, looping through products to get the ones that are not null looping again to convert the products into product names (may want to ask yourself if this is nessasary, seeing as the information that you need to create an OutputResponse is on the Product class, could save yourself a potential looping.
Hope this makes sense.
Taking the https://stackoverflow.com/a/59844773/637968 even further:
private IEnumerable<OutputResponse> GetOutput(IEnumerable<Item> items)
{
return items.SelectMany(x => x.Products ?? Array.Empty<Product>)
.Select(x => new ProductName(x))
.Select(p => new OutputResponse() { Name = product.Name, Description = product.Description});
}
It will iterate twice over the whole collection but OP asked for LOC reduction and not performance improvement.
You can try the following,
private static IEnumerable<OutputResponse> GetOutput(IEnumerable<Item> items) {
return items.SelectMany(x => x.Products)?.Select(x=> new OutputResponse() { Name = new ProductName(x).Name, Description = new ProductName(x).Description });
}
I am trying to refactor some code. So the code I am trying to refactor is this
var userApp = string.Join(",", items.Where(x => x.LicenseType == 1).Select(x => x.GroupName));
var groupApp = string.Join(",", items.Where(x => x.LicenseType == 2).Select(x => x.GroupName));
var totalUsedLicense = GetTotalFreeLicense(schoolCode, userApp, groupApp);
foreach (var item in totalUsedLicense)
{
items.FirstOrDefault(x => x.GroupName == item.GroupName).AvailableLicense = items.FirstOrDefault(x => x.GroupName == item.GroupName).TotalLicense - item.Count;
}
Type of items can be List<ApplicationListDto> or List<AdUserApplicationDto> - they both inherit from BaseApplicationDto,
where the common properties are.
Now I want to make a function where I can pass items as a parameter. How should I do this?
I am trying to get rid of the redundant code here
if (isList)
{
if (data.Count <= 0) return;
List<AdUserApplicationDto> userApplicationDto = data;
var items = userApplicationDto;
var userApp = string.Join(",", items.Where(x => x.LicenseType == 1).Select(x => x.GroupName));
var groupApp = string.Join(",", items.Where(x => x.LicenseType == 2).Select(x => x.GroupName));
var totalUsedLicense = GetTotalFreeLicense(schoolCode, userApp, groupApp);
foreach (var item in totalUsedLicense)
{
items.FirstOrDefault(x => x.GroupName == item.GroupName).AvailableLicense = items.FirstOrDefault(x => x.GroupName == item.GroupName).TotalLicense - item.Count;
}
}
else
{
Page<ApplicationListDto> userApplicationDto = data;
if (userApplicationDto.TotalItems <= 0) return;
var items = userApplicationDto.Items;
var userApp = string.Join(",", items.Where(x => x.LicenseType == 1).Select(x => x.GroupName));
var groupApp = string.Join(",", items.Where(x => x.LicenseType == 2).Select(x => x.GroupName));
var totalUsedLicense = GetTotalFreeLicense(schoolCode, userApp, groupApp);
foreach (var item in totalUsedLicense) {
items.FirstOrDefault(x => x.GroupName == item.GroupName).AvailableLicense = items.FirstOrDefault(x => x.GroupName == item.GroupName).TotalLicense - item.Count;
}
}
If you want a method to accept different types of list with a common base type, do this:
public void SomeAction<T>(List<T> list) where T : BaseApplicationDto
{
// ...
}
You use the type of the base class as the type of the list..
public abstract class Common
{
public string CommonString { get; set; }
}
public class B : Common
{
}
public class A : Common
{
}
public class ABConsumer
{
public void DoSomething(List<Common> myList)
{
List<Common> EmptyStrings = myList.Where(x => x.CommonString == string.Empty).ToList();
}
}
You can now access properties of the base class of both classes.
This is simple inheritance.
Edit
It'll require a cast to from any given type: A or B to Common before it can be passed. If casting is an issue another good example using conditional generics can be used as shown in #ikkentims answer.
class Animal
{
public FoodTypes Food { get;set;}
public string Name { get; set; }
}
enum FoodTypes
{
Herbivorous,
Carnivorous
}
class Util
{
public static Dictionary<FoodTypes,List<Animal>> GetAnimalListBasedOnFoodType(List<Animal> animals)
{
Dictionary<FoodTypes, List<Animal>> map = new Dictionary<FoodTypes, List<Animal>>();
var foodTypes = animals.Select(o => o.Food).Distinct();
foreach(var foodType in foodTypes)
{
if (!map.ContainsKey(foodType))
map.Add(foodType, null);
map[foodType] = animals.Where(o => o.Food == foodType).ToList();
}
return map;
}
}
The above code is to get the idea of what I am trying to achieve. Now, the question is
Is it possible to achieve the functionality of GetAnimalListBasedOnFoodType in a single lambda expression?
Here you go :)
public static Dictionary<FoodTypes, List<Animal>> GetAnimalListBasedOnFoodType(List<Animal> animals)
{
return animals
.GroupBy(animal => animal.Food)
.ToDictionary(
group => group.Key,
group => group.ToList());
}
You want to use the GroupBy method passing in the property that you want to group the animals by. Then, you can use the ToDictionary method to create your dictionary based on the grouping.
For example:
public static Dictionary<FoodTypes, List<Animal>> GetAnimalListBasedOnFoodType(List<Animal> animals)
{
var animalFoodMap = animals.GroupBy(animal => animal.Food)
.ToDictionary(animalGroup => animalGroup.Key, x => animalGroup.ToList());
return animalFoodMap;
}
I was wondering what was the best approach to compare multiple objects that are created and having the state of the objects changed to Inactive (Deleted), while creating history and dependencies.
This also means im comparing past and present objects inside a relational table (MarketCookies).
Id | CookieID | MarketID
The ugly solution i found was calculating how many objects had i changed.
For this purpose lets call the items of the Past: ListP
And the new items: ListF
I divided this method into three steps:
1 - Count both lists;
2 - Find the objects of ListP that are not present in List F and change their state to Inactive and update them;
3 - Create the new Objects and save them.
But this code is very difficult to maintain.. How can i make an easy code to maintain and keep the functionality?
Market Modal:
public class Market()
{
public ICollection<Cookie> Cookies {get; set;}
}
Cookie Modal:
public class Cookie()
{
public int Id {get;set;}
//Foreign Key
public int CookieID {get;set}
//Foreign Key
public int MarketID {get;set;}
}
Code:
public void UpdateMarket (Market Market, int Id)
{
var ListP = MarketCookiesRepository.GetAll()
.Where(x => x.MarketID == Id && Market.State != "Inactive").ToList();
var ListF = Market.Cookies.ToList();
int ListPCount = ListP.Count();
int ListFCount = ListF.Count();
if(ListPCount > ListFCount)
{
ListP.Foreach(x =>
{
var ItemExists = ListF.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Delete the Object
}
});
ListF.Foreach(x =>
{
var ItemExists = ListP.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Create Object
}
});
}
else if(ListPCount < ListFCount)
{
ListF.Foreach(x =>
{
var ItemExists = ListP.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Create Objects
}
});
ListP.Foreach(x =>
{
var ItemExists = ListF.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Delete Objects
}
});
}
else if(ListPCount == ListFCount)
{
ListP.Foreach(x =>
{
var ItemExists = ListF.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Delete Objects
}
});
ListF.Foreach(x =>
{
var ItemExists = ListP.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Create Objects
}
});
}
}
Without a good, minimal, complete code example that clearly illustrates the question, it's hard to know for sure what even a good implementation would look like, never mind "the best". But, based on your description, it seems like the LINQ Except() method would actually serve your needs reasonably well. For example:
public void UpdateMarket (Market Market, int Id)
{
var ListP = MarketCookiesRepository.GetAll()
.Where(x => x.MarketID == Id && Market.State != "Inactive").ToList();
var ListF = Market.Cookies.ToList();
foreach (var item in ListP.Except(ListF))
{
// set to inactive
}
foreach (var item in ListF.Except(ListP))
{
// create new object
}
}
This of course assumes that your objects have overridden Equals() and GetHashCode(). If not, you can provide your own implementation of IEqualityComparer<T> for the above. For example:
// General-purpose equality comparer implementation for convenience.
// Rather than declaring a new class for each time you want an
// IEqualityComparer<T>, just pass this class appropriate delegates
// to define the actual implementation desired.
class GeneralEqualityComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, T, bool> _equals;
private readonly Func<T, int> _getHashCode;
public GeneralEqualityComparer(Func<T, T, bool> equals, Func<T, int> getHashCode)
{
_equals = equals;
_getHashCode = getHashCode;
}
public bool Equals(T t1, T t2)
{
return _equals(t1, t2);
}
public int GetHashCode(T t)
{
return _getHashCode(t);
}
}
Used like this:
public void UpdateMarket (Market Market, int Id)
{
var ListP = MarketCookiesRepository.GetAll()
.Where(x => x.MarketID == Id && Market.State != "Inactive").ToList();
var ListF = Market.Cookies.ToList();
IEqualityComparer<Cookie> comparer = new GeneralEqualityComparer<Cookie>(
(t1, t2) => t1.Id == t2.Id, t => t.Id.GetHashCode());
foreach (var item in ListP.Except(ListF, comparer))
{
// set to inactive
}
foreach (var item in ListF.Except(ListP, comparer))
{
// create new object
}
}
Hello i got some method that generating where statment programmatically how can i move where generation to other class method anyone can help ?
public static List<MME.Objects.TypedLists.InvoiceList> GetList(List<MMPFramework.SearchParameter> parameter)
{
MME.Objects.Invoice Invoice = null;
MME.Objects.Contractor Contractor = null;
MME.Objects.Contract Contract = null;
MME.Objects.TypedLists.InvoiceList invoiceList= null;
var t = MME.DAL.NhSessionHelper.GetCurrentSession().QueryOver<MME.Objects.Invoice>(() => Invoice);
foreach (var searchParameter in parameter)
{
if(searchParameter.Expression == "Like")
{
t.Where(Restrictions.Like(searchParameter.PropertyName, searchParameter.ObjectValueLo));
}
else if (searchParameter.Expression == "Eq")
{
t.Where(Restrictions.Eq(searchParameter.PropertyName, searchParameter.ObjectValueLo));
}
else if (searchParameter.Expression == "Between")
{
t.Where(Restrictions.Between(searchParameter.PropertyName, searchParameter.ObjectValueLo,searchParameter.ObjectValueHi));
}
else if(searchParameter.Expression == "Gt")
{
t.Where(Restrictions.Gt(searchParameter.PropertyName, searchParameter.ObjectValueLo));
}
else if (searchParameter.Expression == "Lt")
{
t.Where(Restrictions.Lt(searchParameter.PropertyName, searchParameter.ObjectValueLo));
}
else
{
//todo more
}
//t.Where(Restrictions.Eq(searchParameter.PropertyName, searchParameter.ObjectValue));
}
t.JoinQueryOver(() => Invoice.Contractor, () => Contractor, JoinType.LeftOuterJoin)
.JoinQueryOver(() => Invoice.Contract, () => Contract, JoinType.LeftOuterJoin)
.Select(Projections.Property(() => Invoice.Id).WithAlias(() => invoiceList.Id),
Projections.Property(() => Invoice.Number).WithAlias(() => invoiceList.InvoiceNumber),
Projections.Property(() => Contractor.Name).WithAlias(() => invoiceList.ContractorName),
Projections.Property(() => Contract.Number).WithAlias(() => invoiceList.ContractNumber)
)
.TransformUsing(Transformers.AliasToBean<MME.Objects.TypedLists.InvoiceList>());
return t.List<MME.Objects.TypedLists.InvoiceList>().ToList();
}
I've tried with this but it seems to not work.... Hope someone was doing something and can help me to handle with it.
public class BaseList
{
public object WhereGenerator(object ob)
{
QueryOver Ded = ob as QueryOver;
return null;
}
}
foreach (var restriction in BaseList.Createrestrictions(parameter))
{
t.Where(restriction);
}
public class BaseList
{
public IEnumerable<AbstractCriterion> Createrestrictions(List<MMPFramework.SearchParameter> parameter)
{
return parameter.Select(ToCritieria);
}
private AbstractCriterion ToCritieria(SearchParameter searchParameter)
{
if(searchParameter.Expression == "Like")
{
return Restrictions.Like(searchParameter.PropertyName, searchParameter.ObjectValueLo);
}
else ...
}
}