Remove an item from a LINQ collection - c#

I think I am putting my question correctly :)
I am querying the database using LINQ to retrieve some data. Please find the code below.
var leadtasktype = _context.LeadTypeTaskTypes.Where(l => l.LeadTypeId == item.Value);
foreach(LeadTypeTaskType l in leadtasktype){
if (l.TaskTypeId == 21)
{
//I need to remove an item which has the tasktype id 21
}
}
As I mentioned in the comments, I need to remove items from the leadtasktype based on my if condition. How do I do this?

This would seem very like another filter condition:
var leadtasktype = _context.LeadTypeTaskTypes
.Where(l => l.LeadTypeId == item.Value)
.Where(l => l.TaskTypeId != 21); // Exclude ID = 21.

var leadtasktype = _context.LeadTypeTaskTypes.Where(l => l.LeadTypeId == item.Value && l.LeadTypeId != 21);

Just leave them out of your set:
var leadtasktype = _context.LeadTypeTaskTypes
.Where(l =>
l.leadTypeId != 21 &&
l.LeadTypeId == item.Value
);

Is it this what you want ?
var leadtasktype = _context.LeadTypeTaskTypes.RemoveAll
(l => l.LeadTypeId == item.Value && l.LeadTypeId == 21);

var leadtasktype = _context.LeadTypeTaskTypes
.Where(l => l.LeadTypeId == item.Value
&& l.TaskTypeId != 21); // Exclude ID = 21.

var leadtasktype = _context.LeadTypeTaskTypes.Where(l => l.LeadTypeId == item.Value);
for (var i = 0; i < leadtasktype.Count; i++)
{
if (leadtasktype[i].TaskTypeId == 21)
{
leadtasktype.RemoveAt(i);
}
}

var leadtasktype = _context.LeadTypeTaskTypes.Where(l => l.LeadTypeId == item.Value);
var newData = leadtasktype;
foreach(LeadTypeTaskType l in leadtasktype){
if (l.TaskTypeId == 21)
{
newData.Remove(l);
}
}

Related

How to add listviewitems to an array when the check can be one or more items in a string array?

Is there anyway to remove the three conditionals and use the one the problem is i can have one or more array lengths dependent on how many times the string can be split by a space.
if (array.Length == 1)
{
list = FamilyDataItems.Cast<ListViewItem>()
.Where(x => x.SubItems
.Cast<ListViewItem.ListViewSubItem>()
.Any(y => y.Text.ToLowerInvariant().Contains(array[0])))
.ToArray();
}
else if (array.Length == 2)
{
list = FamilyDataItems.Cast<ListViewItem>()
.Where(x => x.SubItems
.Cast<ListViewItem.ListViewSubItem>()
.Any(y => y.Text.ToLowerInvariant().Contains(array[0])
&& y.Text.ToLowerInvariant().Contains(array[1])))
.ToArray();
}
else if (array.Length > 2)
{
list = FamilyDataItems.Cast<ListViewItem>()
.Where(x => x.SubItems
.Cast<ListViewItem.ListViewSubItem>()
.Any(y => y.Text.ToLowerInvariant().Contains(array[0])
&& y.Text.ToLowerInvariant().Contains(array[1])
&& y.Text.ToLowerInvariant().Contains(array[2])))
.ToArray();
}
According to your comment above, yes the comments suggestions won't get what you need. I think the following will.
If a SubItem should contain any word from the array:
void Caller()
{
foreach (var item in yourListView.Items.OfType<ListViewItem>())
item.BackColor = SystemColors.Window;
var array = new[] { "door", "double" };
var list = yourListView.Items.Cast<ListViewItem>()
.Where(x => x.SubItems.Cast<ListViewItem.ListViewSubItem>()
.Any(y => array
.Any(z => y.Text.IndexOf(z, StringComparison.OrdinalIgnoreCase) >= 0)));
foreach (var item in list)
item.BackColor = Color.Red;
}
Or if a SubItem should contain all the words of the array:
void Caller()
{
foreach (var item in yourListView.Items.OfType<ListViewItem>())
item.BackColor = SystemColors.Window;
var array = new[] { "door", "double" };
var list = yourListView.Items.Cast<ListViewItem>()
.Where(x => x.SubItems.Cast<ListViewItem.ListViewSubItem>()
.Any(y => array
.All(z => y.Text.IndexOf(z, StringComparison.OrdinalIgnoreCase) >= 0)));
foreach (var item in list)
item.BackColor = Color.Red;
}
You may try something like this -
list = FamilyDataItems.Cast<ListViewItem>()
.Where(
(array.Length == 1 && x => x.SubItems
.Cast<ListViewItem.ListViewSubItem>()
.Any(y => y.Text.ToLowerInvariant().Contains(array[0])))
|| (array.Length == 2 && x => x.SubItems
.Cast<ListViewItem.ListViewSubItem>()
.Any(y => y.Text.ToLowerInvariant().Contains(array[0])
&& y.Text.ToLowerInvariant().Contains(array[1])))
|| (array.Length > 2 && x => x.SubItems
.Cast<ListViewItem.ListViewSubItem>()
.Any(y => y.Text.ToLowerInvariant().Contains(array[0])
&& y.Text.ToLowerInvariant().Contains(array[1])
&& y.Text.ToLowerInvariant().Contains(array[2]))))
).ToArray();
HTH and I didn't miss any parentheses

Update multiple values to object list in c#

How to update multiple property of object in list?
foreach(emp e in emps){
list1.Where(x => x.ID == e.ID && x.Salary < 5000).FirstOrDefault().Level = B;
list1.Where(x => x.ID == e.ID && x.Salary < 5000).FirstOrDefault().Hike = e.Hike;
list1.Where(x => x.ID == e.ID && x.Salary < 5000).FirstOrDefault().Salary = (e.Hike + 100)*e.Salary/100 ;
}
I dont want to use multiple in-line query for each field. Also it should update same single object.
Note : e.ID is not unique key. list1 can contain duplicate Ids
You need to query your list only once
foreach (emp e in emps)
{
var item = list.FirstOrDefault(x => x.ID == e.empID && x.Salary > 5000);
if (item != null)
{
item.Level = B;
item.Hike = e.Hike;
item.Salary = (e.Hike + 100) * e.Salary / 100;
}
}
After giving lots of try. Looks like these will work :
foreach(emp e in emps){
int index = list1.FindIndex(x => x.ID == e.ID && x.Salary < 5000);
if(index != -1)
{
list1[index].Level = 'B';
list1[index].Hike = e.Hike;
list1[index].Salary = (e.Hike + 100)*e.Salary/100;
}
}
What you guys feel ?
Replace Foo with your class
foreach (emp e in emps)
{
if (list.FirstOrDefault(x => x.ID == e.empID && x.Salary > 5000) is Foo f)
{
f.Level = B;
f.Hike = e.Hike;
f.Salary = (e.Hike + 100) * e.Salary / 100;
}
}
I wanted a solution that updates the object in place, which I suspect the OP wants too.
int i = yourList.FindIndex(x => x.ID == "123" && x.Salary < 5000);
if (i > 0) {
yourList[i].Level = "foo";
yourList[i].Hike = "bar";
}
No explicit search, no nested loops: (if ID is your primary Key)
foreach(item in list.Join(emps, x=>x.ID, e=>e.empID, (l,e)=> (l,e)).Where(x => x.l.Salary > 5000))
{
item.l.Level = B;
item.l.Hike = item.e.Hike;
item.l.Salary = (item.e.Hike + 100) * item.e.Salary / 100;
}
Append .OfType() if you need to.

C# LINQ How to find matching item from one list in another list and check for the property in the other list

I would like to loop through a list of item,
find the matching record in another list and
check a property of that item in the new list is enabled/disabled.
if false, break the looping.
Here is my code.
var isDataPresent = true;
foreach (var item in listA)
{
var dataPresent = listB
.FirstOrDefault(x => x.Id == item.Id &&
x.DistributionType == item.DistributionType)
?.IsDataPresent;
if (!dataPresent.GetValueOrDefault())
{
isDataPresent = false;
break;
}
}
return isDataPresent;
Is there a faster/better way to achieve this.
My updated code with JOIN:
var result = listA.Join(listB,
dt => new { dt.Id, dt.DistributionType },
dp => new { dp.Id, dp.DistributionType },
(distType, dataPresent) => new
{
distType.Id,
distType.DistributionType,
dataPresent.IsDataPresent
});
if(result.Any(x => x.IsDataPresent == false))
{
isDataPresent = false;
}
you can change your use of FirstOrDefault() to Any()
that way, you don't need to make other checks and you only need one variable.
var isDataPresent = true;
foreach (var item in listA)
{
isDataPresent = listB.Any(x => x.Id == item.Id &&
x.DistributionType == item.DistributionType && x.IsDataPresent);
if (!isDataPresent)
break;
}
return isDataPresent;
Try with Any like below.
var isDataPresent = !listA.Any(item => !listB
.FirstOrDefault(x => x.Id == item.Id && x.DistributionType == item.DistributionType)
?.IsDataPresent.GetValueOrDefault());
my approach would be .Count()
var countOfA = listA.Count();
var countOfAWithB = listA.Count(a=> listB.Any(b => a.Id == b.Id &&
a.DistributionType == b.DistributionType));
return countOfA == countOfAWithB;
You can achieve by join:
var res = (from dp in dataPresent
from la in listA
where dp.DistributionType == la.DistributionType
select new {
la.isDataPresent }
).ToList()
and there are better solution then join

How to combine the multiple part linq into one query?

Operator should be ‘AND’ and not a ‘OR’.
I am trying to refactor the following code and i understood the following way of writing linq query may not be the correct way. Can somone advice me how to combine the following into one query.
AllCompany.Where(itm => itm != null).Distinct().ToList();
if (AllCompany.Count > 0)
{
//COMPANY NAME
if (isfldCompanyName)
{
AllCompany = AllCompany.Where(company => company["Company Name"].StartsWith(fldCompanyName)).ToList();
}
//SECTOR
if (isfldSector)
{
AllCompany = AllCompany.Where(company => fldSector.Intersect(company["Sectors"].Split('|')).Any()).ToList();
}
//LOCATION
if (isfldLocation)
{
AllCompany = AllCompany.Where(company => fldLocation.Intersect(company["Location"].Split('|')).Any()).ToList();
}
//CREATED DATE
if (isfldcreatedDate)
{
AllCompany = AllCompany.Where(company => company.Statistics.Created >= createdDate).ToList();
}
//LAST UPDATED DATE
if (isfldUpdatedDate)
{
AllCompany = AllCompany.Where(company => company.Statistics.Updated >= updatedDate).ToList();
}
//Allow Placements
if (isfldEmployerLevel)
{
fldEmployerLevel = (fldEmployerLevel == "Yes") ? "1" : "";
AllCompany = AllCompany.Where(company => company["Allow Placements"].ToString() == fldEmployerLevel).ToList();
}
Firstly, unless AllCompany is of some magic custom type, the first line gives you nothing.
Also I have a doubt that Distinctworks the way You want it to. I don't know the type of AllCompany but I would guess it gives you only reference distinction.
Either way here'w what I think You want:
fldEmployerLevel = (fldEmployerLevel == "Yes") ? "1" : "";
var result = AllCompany.Where(itm => itm != null)
.Where(company => !isfldCompanyName || company["Company Name"].StartsWith(fldCompanyName))
.Where(company => !isfldSector|| fldSector.Intersect(company["Sectors"].Split('|')).Any())
.Where(company => !isfldLocation|| fldLocation.Intersect(company["Location"].Split('|')).Any())
.Where(company => !isfldcreatedDate|| company.Statistics.Created >= createdDate)
.Where(company => !isfldUpdatedDate|| company.Statistics.Updated >= updatedDate)
.Where(company => !isfldEmployerLevel|| company["Allow Placements"].ToString() == fldEmployerLevel)
.Distinct()
.ToList();
Edit:
I moved Distinct to the end of the query to optimize the processing.
How about trying like this;
AllCompany = AllCompany .Where(company => (company => company.Statistics.Created >= createdDate)) && (company.Statistics.Updated >= updatedDate));
If every part of query is optional (like created date, last update date..) then you can build linq query string.
Here's a sneaky trick. If you define the following extension method in its own static class:
public virtual IEnumerable<T> WhereAll(params Expression<Predicate<T> filters)
{
return filters.Aggregate(dbSet, (acc, element) => acc.Where(element));
}
then you can write
var result = AllCompany.WhereAll(itm => itm != null,
company => !isfldCompanyName || company["Company Name"].StartsWith(fldCompanyName),
company => !isfldSectorn || fldSector.Intersect(company["Sectors"].Split('|')).Any(),
company => !isfldLocation || fldLocation.Intersect(company["Location"].Split('|')).Any(),
company => !isfldcreatedDate || company.Statistics.Created >= createdDate,
company => !isfldUpdatedDate || company.Statistics.Updated >= updatedDate,
company => !isfldEmployerLevel || company["Allow Placements"].ToString() == fldEmployerLevel)
.Distinct()
.ToList();

LINQ: Rewrite an inline query into Linq method style?

How could this be re-written using LINQ methods instead of inline query style?
var cp = from DataRow r in rptDataPkg.Datasets.Item(0).Result.Rows
where (r.Field<string>("UnitItem") == "PC") &&
(r.Field<string>("UnitItem") == "Hs") &&
(r.Field<string>("UnitItem") == "U")
select new CurrProjected
{
doAddUp = (r.Field<Decimal>("Fld1") + r.Field<Decimal>("Fld2"))
== r.Field<Decimal>("Fld3")
};
I prefer this syntax to the other solutions, personally.
var cp = rptDataPkg.Datasets.Item(0).Result.Rows
.Where(r => r.Field("UnitItem") == "PC")
.Where(r => r.Field("UnitItem") == "Hs")
.Where(r => r.Field("UnitItem") == "U")
.Select(r => new CurrProjected
{
doAddUp = (r.Field("Fld1") + r.Field("Fld2"))
== r.Field("Fld3")
});
Try the following
var cp = rptDataPkg.Datasets.Item(0).Result.Rows
.Cast<DataRow>()
.Where(r => (r.Field<string>("UnitItem") == "PC") &&
(r.Field<string>("UnitItem") == "Hs") &&
(r.Field<string>("UnitItem") == "U"))
.Select(r => new CurrProjected
{
doAddUp = (r.Field<Decimal>("Fld1") + r.Field<Decimal>("Fld2"))
== r.Field<Decimal>("Fld3")
});

Categories