Converting Foreach loop into linq form - c#

I have Dictionary<string,List<Member> members and I have foreach loops. How to covert loop in loop into linq expression?
members.Foreach(x => x.Where(a=>a.Firstaname ?
foreach (var key in games.Keys)
{
foreach (var val in games[key])
{
if (firstName == val.FirstName && lastName == val.LastName && command == val.CommandName)
{
val.Position = position;
}
}
}
need to set player's position if it matches data in dictionary

var items = games.SelectMany(x => x.Value).Where(val => firstName == val.FirstName && lastName == val.LastName && command == val.CommandName);
foreach(var i in items)
{
i.Position = position;
}

Related

Getting System.StackOverflowException , in a recursive function call?

I have to two function which is used to find tags inside the tags like, there is a tag A=B(C(D(E))) so i have to find all the tags inside B then all the tags inside C and so on. I write two function but getting the error System.StackOverflowException. In the first function i am providing the tag ID and against that tag id i am getting getNestesCalTagsId and then calling the getNestedCalTagsIngredients() function. But when there are lot of recursion calls i get the error System.StackOverflowException. Below is my whole code.
public List<int?> getNestedCalTags(int? calTagId)
{
var getNestesCalTagsId = db.Dependencies_Metrix.Where(x => x.Cal_Tag_P_Id == calTagId && x.Status == true && x.Cal_Tag_Id_FK!=null).Select(x => x.Cal_Tag_Id_FK).ToList();
if (getNestesCalTagsId.Count > 0)
{
nestedCalFTags.AddRange(getNestesCalTagsId);
foreach (var item in getNestesCalTagsId)
{
if (item != null)
{
getNestedCalTagsIngredients(item.Value);
}
}
}
if (nestedCalFTags.Count > 0)
{
int countedTags = nestedCalFTags.Count;
List<int?> tags = new List<int?>(nestedCalFTags);
for (int i = 0; i < tags.Count; i++)
{
if (tags[i] != null)
{
getNestedCalTagsIngredients(tags[i].Value);
}
}
}
return nestedRawTags;
}
public bool getNestedCalTagsIngredients(int nestCalTagId)
{
var getCalTags = db.Dependencies_Metrix.Where(x => x.Cal_Tag_P_Id == nestCalTagId && x.Status == true).ToList();
if (getCalTags.Count > 0)
{
foreach (var item in getCalTags)
{
if (item.Cal_Tag_Id_FK != null)
{
var getNestedCalTagParent = db.Dependencies_Metrix.Where(x => x.Cal_Tag_P_Id == item.Cal_Tag_Id_FK && x.Status == true && x.Cal_Tag_Id_FK!=null).Select(x => x.Cal_Tag_Id_FK).ToList();
if (getNestedCalTagParent != null)
{
nestedCalFTags.AddRange(getNestedCalTagParent);
getNestedCalTags(item.Cal_Tag_Id_FK);
}
}
else
{
var rawTagId = db.Dependencies_Metrix.Where(x => x.Cal_Tag_P_Id == item.Cal_Tag_P_Id && x.Real_Tag_Id_FK!=null).Select(x => x.Real_Tag_Id_FK).ToList();
if (rawTagId != null)
{
foreach (var rawItem in rawTagId)
{
if (rawItem!=null)
{
if (nestedRawTags.IndexOf(rawItem.Value) == -1)
{
nestedRawTags.Add(rawItem.Value);
}
}
}
}
nestedCalFTags.Remove(nestCalTagId);
}
}
}
return true;
}

Removing Duplicate rows from IEnumerable

I would like to know how you would remove duplicate rows from a IEnumerable. I have this code:
public IEnumerable <Shipments> Shipments
{
get
{
Debug.Print("Initiated");
foreach (var item in Loads)
{
if (item.ShipTo.Contains(" "))
{
foreach (var item2 in Routes.Where(d => d.DockCode == item.ShipTo.Substring(0, item.ShipTo.IndexOf(" ")) && d.CarrierDeparture.TimeOfDay == item.ShipTime.TimeOfDay))
{
yield return new Shipments() { Arrival = item2.CarrierArrival, Departure = item2.CarrierDeparture, Issuer = item.Customer, Destination = item.ShipTo, LoadType = item.LoadType };
}
}
}
}
}
which gives me this data using it as a item source
My goal is to only return new shipment if one that is the same doesn't exist. How would I go about doing that?
You could create a class that implements IEqualityComparer<Routes>:
class RoutesComparer : IEqualityComparer<Routes>
{
// Might want to add null checks here.
public bool Equals(Routes route1, Routes route2) =>
route1.DockCode == route2.DockCode
&& route1.CarrierArrival == route2.CarrierArrival;
public int GetHashCode(Routes obj) =>
obj.DockCode.GetHashCode() ^ (obj.CarrierArrival.GetHashCode() * 13);
}
Then pass that to .Distinct().
foreach (var item2 in Routes.Where(d => d.DockCode == item.ShipTo.Substring(0, item.ShipTo.IndexOf(" "))
&& d.CarrierDeparture.TimeOfDay == item.ShipTime.TimeOfDay).Distinct(new RoutesComparer()))

LINQ "OR" in expression

Just trying to get a cleaner code on a delete method. I need to delete records from a database if a certain column value matches one of two columns in another table.
Is there a better way to delete multiple records, with a "OR"-like expression, so that I can have only one for each loop instead of the following two?
public static void DeleteStageById(int StageId, int ApplicationId)
{
using (IPEntities ip = IPEntities.New())
{
var stage = ip.mkStages;
var stageCultures = ip.appObjectCultures;
var stageStates = ip.mkStatesInStages;
foreach (var stageCulture in stageCultures.Where(sC => sC.ObjectCultureId == stage.Where(s => s.StageId == StageId && s.ApplicationId == ApplicationId).FirstOrDefault().OCId_Name))
{
stageCultures.DeleteObject(stageCulture);
}
foreach (var stageCulture in stageCultures.Where(sC => sC.ObjectCultureId == stage.Where(s => s.StageId == StageId && s.ApplicationId == ApplicationId).FirstOrDefault().OCId_Description))
{
stageCultures.DeleteObject(stageCulture);
}
...
ip.SaveChanges();
}
}
my linq would look like this one
var stage = ip.mkStages;
var stageCultures = ip.appObjectCultures;
var stageStates = ip.mkStatesInStages;
//store this result into a temp variable so it only needs to run once
var temp = stage.Where(s => s.StageId == StageId && s.ApplicationId == ApplicationId).FirstOrDefault();
if (temp != null)
{
foreach (var stageCulture in stageCultures.Where(sC => sC.ObjectCultureId == temp.OCId_Name || sC.ObjectCultureId == temp.OCId_Description))
{
stageCultures.DeleteObject(stageCulture);
}
...
ip.SaveChanges();
}
I recommend avoiding confusing expressions, but here you go:
foreach (var stageCulture in stageCultures.Where(sC => {
var v = stage.Where(s => s.StageId == StageId && s.ApplicationId == ApplicationId).FirstOrDefault();
return sC.ObjectCultureId == v.OCId_Name || sC.ObjectCultureId == v.OCId_Description;
})
{
stageCultures.DeleteObject(stageCulture);
}

Dynamic Linq Build Where Clause many Parameters

I will explain my Problem
so Firstly, I use Predicates Linq for Build Where clause dynamically.
I have to build dynamically because I don't know how many parameters will come. Let me give an example. For the A column can be one parameters however, for the B column can be 2 parameters like either value 'Gas' or 'Oil' which select but that's big problem I can not combine for these 2 column correctly.
So as a result, this code work but It return 0 Items. But there are I know.
public List<CarEntity> GetSearchByKCriteria(int cityId, List<string> fuelType, List<string> gearType, List<string> budget,
List<string> caroser, List<string> enginePower)
{
Expression<Func<Car, bool>> query = null;
Expression<Func<Car, bool>> combine = null;
foreach (var bud in budget)
{
if (budget.Count >= 1)
{
if (bud == "1")
{
if (budget.Count > 1)
{
query = car => car.Budget >= 20000 && car.Budget <= 34999;
}
else
{
query = car => car.Budget >= 20000 && car.Budget <= 34999;
}
}
else if (bud == "2")
{
if (query != null)
{
combine = car => (car.Budget >= 35000 && car.Budget <= 49999);
query = query.Or(combine);
}
else
{
query = car => car.Budget >= 35000 && car.Budget <= 49999;
}
}
}
}
foreach (var caros in caroser)
{
if (caros != "-1" && !string.IsNullOrEmpty(caros))
{
if (query != null)
{
if (query.Expand().ToString().ToLower().Contains("karoser"))
{
combine = car => (car.Karoser == caros);
query = query.And(combine);
}
else
{
combine = car => car.Karoser == caros;
query = query.And(combine);
}
}
else
{
query = car => car.Karoser == caros;
}
}
}
foreach (var fuel in fuelType)
{
if (fuel != "-1" && !string.IsNullOrEmpty(fuel))
{
if (query != null)
{
if (query.Expand().ToString().ToLower().Contains("yakituru"))
{
combine = car => (car.YakitTuru==fuel);
query = query.Or(combine);
}
else
{
combine = car => car.YakitTuru == fuel;
query = query.And(combine);
}
}
else
{
query = car => car.YakitTuru == fuel;
}
}
}
foreach (var gear in gearType)
{
if (gear!="-1"&& !string.IsNullOrEmpty(gear))
{
if (query != null)
{
if (query.Expand().ToString().ToLower().Contains("sanzimantipi"))
{
combine = car => (car.SanzimanTipi == gear);
query = query.Or(combine);
}
else
{
combine = car => car.SanzimanTipi == gear;
query = query.And(combine);
}
}
else
{
query = car => car.SanzimanTipi == gear;
}
}
}
foreach (var engine in enginePower)
{
if (enginePower.Count >= 1)
{
if (engine == "1")
{
if (query != null)
{
if (query.Expand().ToString().ToLower().Contains("silindirhacmi"))
{
combine = car => (car.SilindirHacmi >= 0 && car.SilindirHacmi <= 1600);
query = query.Or(combine);
}
else
{
combine = car => (car.SilindirHacmi >= 0 && car.SilindirHacmi <= 1600);
query = query.And(combine);
}
}
else
{
query = car => car.SilindirHacmi >= 0 && car.SilindirHacmi <= 1600;
}
}
if (engine == "3")
{
if (query != null)
{
if (query.Expand().ToString().ToLower().Contains("silindirhacmi"))
{
combine = car => (car.SilindirHacmi >= 1601 && car.SilindirHacmi <= 1800);
query = query.Or(combine);
}
else
{
combine = car => (car.SilindirHacmi >= 1601 && car.SilindirHacmi <= 1800);
query = query.And(combine);
}
}
else
{
query = car => car.SilindirHacmi >= 1601 && car.SilindirHacmi <= 1800;
}
}
}
using (var context = DataContextFactory.CreateContext())
{
var result = (from fkCar in context.Car.Where(query)
join pkCarBrand in context.CarBrand on fkCar.Marka equals pkCarBrand.ID
where fkCar.IsActive == true
select new
{
entity = fkCar,
joinEntity = pkCarBrand
});
List<CarEntity> theCarList = new List<CarEntity>();
foreach (var item in result)
{
CarEntity theEntity = Mapper.Map(item.entity);
theEntity.CarBrand = Mapper.Map(item.joinEntity);
theCarList.Add(theEntity);
}
return theCarList;
}
}
So thanks for reply,
I faced a similar challenge a while back, where I wanted to have a list of allowed values for an attribute where, if matched, the associated instance would pass the filter. I came up with the following extension method:
static public Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
{
if (null == valueSelector)
{
throw new ArgumentNullException("valueSelector");
}
if (null == values) { throw new ArgumentNullException("values"); }
ParameterExpression p = valueSelector.Parameters.Single();
if (!values.Any())
{
return e => false;
}
var equals = values.Select(value => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));
var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));
return Expression.Lambda<Func<TElement, bool>>(body, p);
}
This is based on the discussion and code posted at http://www.velocityreviews.com/forums/t645784-linq-where-clause.html

optimising linq queries to incres

I have the the below linq queries searching a the same data table and was wondering if it would be possible to make one search and do the below for loops to add data to to the same variables so that it can make the system faster.
var sort = configurationData.AsEnumerable().Where(sorts => sorts.Field<String>("QuestionStartText") == question &&
sorts.Field<String>("slideNo") == Convert.ToString(slideNumber) )
.Select(sorted => sorted.Field<String>("SortByColumn")).Distinct().AsParallel();
var rowNeedAfterSort = configurationData.AsEnumerable().Where(sorts => sorts.Field<String>("QuestionStartText") == question &&
sorts.Field<String>("slideNo") == Convert.ToString(slideNumber))
.Select(sorted => sorted.Field<String>("NoOfRows")).Distinct().AsParallel();
var indexs = configurationData.AsEnumerable().Where(sorts => sorts.Field<String>("QuestionStartText") == question &&
sorts.Field<String>("slideNo") == Convert.ToString(slideNumber))
.Select(sorted => sorted.Field<String>("ColumnInExcel")).Distinct().AsParallel();
int p = 0;
int chartValue = 0;
foreach (string inedcies in indexs)
{
if (inedcies != null)
{
if (!inedcies.ToUpper().Equals("NULL"))
{
if (inedcies.Contains(','))
{
Array.Clear(valuesUsed, 0, valuesUsed.Length);
string[] index = inedcies.Split(',');
foreach (string a in index)
{
valuesUsed[p] = Convert.ToInt32(a);
p++;
}
}
else if (inedcies.Equals("7"))
{
Array.Clear(valuesUsed, 0, valuesUsed.Length);
valuesUsed[p] = Convert.ToInt32(inedcies);
}
else
{
chartValue = Convert.ToInt32(inedcies);
}
}
}
}
foreach (string sortedint in sort)
{
if (sortedint != null)
{
if (!sortedint.ToUpper().Equals("NULL"))
{
SortData2(sortedint);
sortedData = "true";
}
}
}
foreach (string rows in rowNeedAfterSort)
{
if (rows != null)
{
if (!rows.ToUpper().Equals("NULL"))
{
string[] values = rows.Split(' ');
rowCount = Convert.ToInt32(values[1]);
}
}
}
Once you clean up the below codesmell you will be able to see how/where you can take out the foreach loops.
foreach (string a in index)
{
valuesUsed[p] = Convert.ToInt32(a);
p++;
}
what assurances do we have that index.length < valuesUsed.length ?
Foreach (x in y)
{
if (x != null)
{
do something
}
}
More readable. You also do not need to check if an element is null in a foreach loop. The properties of the element may need to be checked, but not the element itself.
y.Foreach(x => do what you need here)

Categories