I have a class ABC like this
public class ABC{
public int Id {get;set;}
public int UserCount {get;set;}
}
Now I add following records to a list of type ABC
List<ABC> lstABC = new List<ABC>();
lstABC.Add(new ABC(){Id=1,UserCount=5});
lstABC.Add(new ABC(){Id=2,UserCount=15});
lstABC.Add(new ABC(){Id=3,UserCount=3});
lstABC.Add(new ABC(){Id=4,UserCount=20});
lstABC.Add(new ABC(){Id=5,UserCount=33});
lstABC.Add(new ABC(){Id=6,UserCount=21});
I've another list of type int
List<int> lstIds = new List<int>();
lstIds.Add(1);
lstIds.Add(3);
lstIds.Add(4);
Now i want to remove all the items from lstABC whose Id's do not match in lstIds without using any loops. What is the most optimized way to do this?
you can just use RemoveAll like this :
lstABC.RemoveAll(x => !lstIds.Contains(x.Id));
it should work easily
Continuing #Coder1409 solution, use HashSet to boost performance (for big collections):
HashSet<int> hashSet = new HashSet<int>(lstIds);
lstABC.RemoveAll(x => !hashSet.Contains(x.Id));
HTH
Another solution somewhat simpler to read
lstABC = (from l in lstABC
where lstIds.Contains(l.Id)
select l).ToList();
Instead of removing you can also select only the matching elements
Related
How do I check if a Guid value is inside a LIST of Structures?
public struct Info
{
public Guid EntityTypeID;
public String Name;
}
List<Info> InfoList = <function which populates the list of Struct>
...
var values = ctx.EntityValues.Where(v => v.EntityID == e.ID
&& InfoList.Contains(v.EntityTypeItemID)).ToList(); <=== problem here!
//or something like: InfoList[i].EntityTypeID.Contains(v.EntityTypeItemID)).ToList();
Thank you
I suspect you're looking for Any:
... InfoList.Any(x => x.EntityTypeID == v.EntityTypeItemID)
You can't use Contains, because you're looking for something which matches part of the item.
(I'd also strongly discourage using public fields and indeed having mutable structures at all, but that's a different matter.)
Another option would be to create a list of the GUIDs you're interested in:
var guids = InfoList.Select(x => x.EntityTypeID).ToList();
Then you can use:
... guids.Contains(v.EntityTypeItemID)
That may work where the previous code didn't, as it moves the extraction of the type ID out of the main query.
Basically all I'm looking to do is something like the following:
string EntityFrameworkType = "Product";
string searchField = "ProductName";
string searchValue = "My Product";
using( var context = new entitycontext())
{
var result = (from x in context.EntityFrameworkType.Where(l=>l.searchField == searchValue) select x).FirstOrDefault();
}
of course this syntax won't work because context does not contain an entity called "EntityFrameworkType"...
Is it possible to do this another way??? What I'm looking to do in generalize my database duplicate check. In this example, I'm searching for any Product with the Name "My Product". But I'd like to be able to pass in these string for say, ProductCategory with ProductCategoryId = 1.... etc...
you can have a look here to get the idea of how it is done.
You'll need to learn about Expression
I am attempting to get unique values in a list of similar value distinguished only by a one element in a pipe delimited string... I keep getting at least one object must implement Icomparable. I don't understand why I keep getting that. I am able to groupBy that value... Why can't I find the max... I guess it is looking for something to compare it with. If I get the integer version will it stop yelling at me? This is the last time I am going to try using LINQ...
var queryResults = PatientList.GroupBy(x => x.Value.Split('|')[1]).Select(x => x.Max());
I know I can get the unique values some other way. I am just having a hard time figuring it out. In that List I know that the string with the highest value amongst its similar brethren is the one that I want to add to the list. How can I do that? I am totally drawing a blank because I have been trying to get this to work in linq for the last few days with no luck...
foreach (XmlNode node in nodeList)
{
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(node.OuterXml);
string popPatInfo = xDoc.SelectSingleNode("./template/elements/element[#name=\"FirstName\"]").Attributes["value"].Value + ", " + xDoc.SelectSingleNode("./template/elements/element[#name=\"LastName\"]").Attributes["value"].Value + " | " + DateTime.Parse(xDoc.SelectSingleNode("./template/elements/element[#name=\"DateOfBirth\"]").Attributes["value"].Value.Split('T')[0]).ToString("dd-MMM-yyyy");
string patientInfo = xDoc.SelectSingleNode("./template/elements/element[#name=\"PatientId\"]").Attributes["value"].Value + "|" + xDoc.SelectSingleNode("./template/elements/element[#name=\"PopulationPatientID\"]").Attributes["enc"].Value;// +"|" + xDoc.SelectSingleNode("./template/elements/element[#name=\"AdminDate\"]").Attributes["value"].Value;
int enc = Int32.Parse(patientInfo.Split('|')[1]);
if (enc > temp)
{
lastEncounter.Add(enc, patientInfo);
temp = enc;
}
//lastEncounter.Add(Int32.Parse(patientInfo.Split('|')[1]));
PatientList.Add( new SelectListItem { Text = popPatInfo, Value = patientInfo });
}
I was thinking about using some kind of temp variable to find out what is the highest value and then add that string to the List. I am totally drawing a blank however...
Here I get the IDs in an anonymous type to make it readable.
var patientEncounters= from patient in PatientList
let PatientID=Int32.Parse(patient.Value.Split('|')[0])
let EncounterID=Int32.Parse(patient.Value.Split('|')[1])
select new { PatientID, EncounterID };
Then we group by UserID and get the last encounter
var lastEncounterForEachUser=from pe in patientEncounters
group pe by pe.PatientID into grouped
select new
{
PatientID=grouped.Key,
LastEncounterID=grouped.Max(g=>g.EncounterID)
};
Linq doesn't know how to compare 2 Patient objects, so it can't determine which one is the "greatest". You need to make the Patient class implement IComparable<Patient>, to define how Patient objects are compared.
// Compare objets by Id value
public int CompareTo(Patient other)
{
return this.Id.CompareTo(other.Id);
}
Another option is to use the MaxBy extension method available in Jon Skeet's MoreLinq project:
var queryResults = PatientList.GroupBy(x => x.Value.Split('|')[1])
.Select(x => x.MaxBy(p => p.Id));
EDIT: I assumed there was a Patient class, but reading your code again, I realize it's not the case. PatientList is actually a collection of SelectListItem, so you need to implement IComparable in that class.
I know this as asked many times but cannot see something that works.
I am reading a csv file and then I have to remove duplicate lines based on one of the columns "CustomerID".
Basically the CSV file can have multiple lines with the same customerID.
I need to remove the duplicates.
//DOES NOT WORK
var finalCustomerList = csvCustomerList.Distinct().ToList();
I have also tried this extension method //DOES NOT WORK
public static IEnumerable<t> RemoveDuplicates<t>(this IEnumerable<t> items)
{
return new HashSet<t>(items);
}
What works for me is
I Read the CSV file into a csvCustomerList
Loop through csvCustomerList and check if a
customerExists If it doesnt I add
it.
foreach (var csvCustomer in csvCustomerList)
{
var Customer = new customer();
customer.CustomerID = csvCustomer.CustomerID;
customer.Name = csvCustomer.Name;
//etc.....
var exists = finalCustomerList.Exists(x => x.CustomerID == csvCustomer.CustomerID);
if (!exists)
{
finalCustomerList.Add(customer);
}
}
Is there a better way of doing this?
For Distinct to work with non standard equality checks, you need to make your class customer implement IEquatable<T>. In the Equals method, simply compare the customer ids and nothing else.
As an alternative, you can use the overload of Distinct that requires an IEqualityComparer<T> and create a class that implements that interface for customer. Like that, you don't need to change the customer class.
Or you can use Morelinq as suggested by another answer.
For a simple solution, check out Morelinq by Jon Skeet and others.
It has a DistinctBy operator where you can perform a distinct operation by any field. So you could do something like:
var finalCustomerList = csvCustomerList.DistinctBy(c => c.customerID).ToList();
I'm trying to use LINQ to return a list of ids given a list of objects where the id is a property. I'd like to be able to do this without looping through each object and pulling out the unique ids that I find.
I have a list of objects of type MyClass and one of the properties of this class is an ID.
public class MyClass
{
public int ID { get; set; }
}
I want to write a LINQ query to return me a list of those Ids.
How do I do that, given an IList<MyClass> such that it returns an IEnumerable<int> of the ids?
I'm sure it must be possible to do it in one or two lines using LINQ rather than looping through each item in the MyClass list and adding the unique values into a list.
IEnumerable<int> ids = list.Select(x=>x.ID).Distinct();
Use the Distinct operator:
var idList = yourList.Select(x=> x.ID).Distinct();
Using straight LINQ, with the Distinct() extension:
var idList = (from x in yourList select x.ID).Distinct();
When taking Distinct, we have to cast into IEnumerable too. If the list is <T> model, it means you need to write code like this:
IEnumerable<T> ids = list.Select(x => x).Distinct();
int[] numbers = {1,2,3,4,5,3,6,4,7,8,9,1,0 };
var nonRepeats = (from n in numbers select n).Distinct();
foreach (var d in nonRepeats)
{
Response.Write(d);
}
Output
1234567890