find inside array of objects - c#

i have a objectA
public class objectA
{
public int Id;
public string Name;
}
i have a list of objectA
List<objectA> list;
i want to find in the list any objectA with Id = 10;
is there linq syntax for this or do i simply have to write a loop here.

list.Where(o => o.Id == 10);
Remember: you can chain those method calls, or you can use the IEnumerable returned here for things like databinding.

To return all objects with an Id of ten, you'll need:
list.Where(o => o.Id = 10)

Related

Linq: Select KeyValuePair from dictionary where value is a list of objects

I have a field that looks like:
public Dictionary<ClassA, List<ClassB>> MyDict;
Assume that:
public class ClassA
{
public string Name;
public int Id;
}
public class ClassB
{
public string Tag;
public string Text;
}
I'm trying to define a query that is of IEnumerable<KeyValuePair<ClassA,IEnumerable<ClassB>> type where I define a condition on the value of ClassB.Tag. I tried things like:
IEnumerable<KeyValuePair<ClassA,IEnumerable<ClassB>> q =
MyDict.Where(pair => pair.Value.Any(b => b.Tag == "a tag"));
But obviously the above is not what I need because it returns the whole List<ClassB> if any item matches that condition, while what I want is to return an IEnumrable or a List of items that match the condition.
dotNetFiddle demo
You need to construct the IEnumerable from a call to ToDictionary, where you use a projection to only take the matching BClass from the list and only take the result from that set where values in the BClass list were actually matched.
IEnumerable<KeyValuePair<ClassA,List<ClassB>>> q = MyDict.ToDictionary(
k => k.Key,
k => k.Value.Where(b => b.Tag == "10").ToList()
).Where(kv => kv.Value.Any());

Is there a way to select two values into same IEnumerable using LINQ in C#?

I have a class that has two integers in it, for example A and B:
public class MyClass {
public int A { get; set; }
public int B { get; set; }
...other stuff...
}
I have a MyCollection of type ObservableCollection<MyClass> in code, and have a need to get an IEnumerable<int> of ALL the values -- both A's and B's -- together in one list.
I have figured out how to do it with quite verbose code (significantly simplified to be only one level below for example purposes, but actually 3 levels of "from" calls and selecting values from within nested lists):
IEnumerable<int> intsA=
(from x in MyCollection
select x.A);
IEnumerable<int> intsB =
(from x in MyCollection
select x.B);
IEnumerable<int> allInts = intsA.Concat(intsB);
It seems like there should be a way to select both variables at the same time into the same IEnumerable<int>. Obviously below doesn't work, but I'd love something like
IEnumerable<int> allInts = (from x in MyCollection select x.A, x.B);
Does something like this exist that is more elegant than what I have above?
I found how to select multiple values into an anonymous type here, but that doesn't make it into the same IEnumerable and still requires more code/processing to get the items out.
(BTW, using .NET 4.5.1, if that makes a difference.) Thanks!
You could use SelectMany:
var result = source.SelectMany(x => new[] { x.A, x.B });
But because you'd allocate a new array for each object, I don't know how performance it will be (or maybe you don't care about it that much).
You could declare GetIntValues on your type which would return IEnumerable<int>:
public class MyClass {
public int A { get; set; }
public int B { get; set; }
...other stuff...
public IEnumerable<int> GetIntValues()
{
yield return A;
yield return B;
}
}
And use it like this:
var result = source.SelectMany(x => x.GetIntValues());
But there is still an additional allocation for each element.
That's pretty easy indeed:
IEnumerable<int> allInts = MyCollection.Select(i => i.A)
.Concat(MyCollection.Select(i => i.B));
It's equivalent to what you wrote, but less verbose. It's using the lambda syntax instead of query comprehension syntax.
Use it if you want to avoid additional allocations. If you don't care about GC pressure, Marcin's solution is even shorter. Also, this outputs the elements in a different order than his solution.

sorting list in a list

I have two classes
public class X
{
string title;
}
public class Y
{
string name;
IList<X> testList;
}
I have a list like below
IList<Y> myList = new List<Y>();
I want to sort myList based on the name and title
How can I do it?
Try something like this,
var sorted = lstY.OrderBy(c => c.name).ToList().Select(d => { d.testList.OrderBy(f => f.title); return d; });
myList.OrderBy(x => x.name).ThenBy(y => y.testList.Min(z=>z.title));
This is one option but not the only option. Add a public or internal getter to class Y:
public IEnumerable<X> TestList{get{return testList.OrderBy(x=>x.title);}}
When retrieving your list of Y, clearly you can sort it by name:
myList.OrderBy(y=>y.name);
And for whatever processing you are doing, such as diplaying the list of Y, you would display Y.name and foreach X in TestList the X.title will be sorted.
or even without that second getter:
myList.OrderBy(y=>y.name).Select(y=>new{y.name, testList=y.testList.OrderBy(t=>t.title)}).Dump();

Using .Select and .Where in a single LINQ statement

I need to gather Distinct Id's from a particular table using LINQ. The catch is I also need a WHERE statement that should filter the results based only from the requirements I've set. Relatively new to having to use LINQ so much, but I'm using the following code more or less:
private void WriteStuff(SqlHelper db, EmployeeHelper emp)
{
String checkFieldChange;
AnIList tableClass = new AnIList(db, (int)emp.PersonId);
var linq = tableClass.Items
.Where(
x => x.UserId == emp.UserId
&& x.Date > DateBeforeChanges
&& x.Date < DateAfterEffective
&& (
(x.Field == Inserted)
|| (x.Field == Deleted)))
)
).OrderByDescending(x => x.Id);
if (linq != null)
{
foreach (TableClassChanges item in linq)
{
AnotherIList payTxn = new AnotherIList(db, item.Id);
checkFieldChange = GetChangeType(item.FieldName);
// Other codes that will retrieve data from each item
// and write it into a text file
}
}
}
I tried to add .Distinct for var linq but it's still returning duplicate items (meaning having the same Id's). I've read through a lot of sites and have tried adding a .Select into the query but the .Where clause breaks instead. There are other articles where the query is somehow different with the way it retrieves the values and place it in a var. I also tried to use .GroupBy but I get an "At least one object must implement IComparable" when using Id as a key.
The query actually works and I'm able to output the data from the columns with the specifications I require, but I just can't seem to make .Distinct work (which is the only thing really missing). I tried to create two vars with one triggering a distinct call then have a nested foreach to ensure the values are just unique, but will thousands of records to gather the performance impact is just too much.
I'm unsure as well if I'd have to override or use IEnumerable for my requirement, and thought I'd ask the question around just in case there's an easier way, or if it's possible to have both .Select and .Where working in just one statement?
Did you add the Select() after the Where() or before?
You should add it after, because of the concurrency logic:
1 Take the entire table
2 Filter it accordingly
3 Select only the ID's
4 Make them distinct.
If you do a Select first, the Where clause can only contain the ID attribute because all other attributes have already been edited out.
Update: For clarity, this order of operators should work:
db.Items.Where(x=> x.userid == user_ID).Select(x=>x.Id).Distinct();
Probably want to add a .toList() at the end but that's optional :)
In order for Enumerable.Distinct to work for your type, you can implement IEquatable<T> and provide suitable definitions for Equals and GetHashCode, otherwise it will use the default implementation: comparing for reference equality (assuming that you are using a reference type).
From the manual:
The Distinct(IEnumerable) method returns an unordered sequence that contains no duplicate values. It uses the default equality comparer, Default, to compare values.
The default equality comparer, Default, is used to compare values of the types that implement the IEquatable generic interface. To compare a custom data type, you need to implement this interface and provide your own GetHashCode and Equals methods for the type.
In your case it looks like you might just need to compare the IDs, but you may also want to compare other fields too depending on what it means for you that two objects are "the same".
You can also consider using DistinctBy from morelinq.
Note that this is LINQ to Objects only, but I assume that's what you are using.
Yet another option is to combine GroupBy and First:
var query = // your query here...
.GroupBy(x => x.Id)
.Select(g => g.First());
This would also work in LINQ to SQL, for example.
Since you are trying to compare two different objects you will need to first implement the IEqualityComparer interface. Here is an example code on a simple console application that uses distinct and a simple implementation of the IEqualityComparer:
class Program
{
static void Main(string[] args)
{
List<Test> testData = new List<Test>()
{
new Test(1,"Test"),
new Test(2, "Test"),
new Test(2, "Test")
};
var result = testData.Where(x => x.Id > 1).Distinct(new MyComparer());
}
}
public class MyComparer : IEqualityComparer<Test>
{
public bool Equals(Test x, Test y)
{
return x.Id == y.Id;
}
public int GetHashCode(Test obj)
{
return string.Format("{0}{1}", obj.Id, obj.Name).GetHashCode();
}
}
public class Test
{
public Test(int id, string name)
{
this.id = id;
this.name = name;
}
private int id;
public int Id
{
get { return id; }
set { id = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
I hope that helps.
Do you passed a IEqualityComparer<T> to .Distinct()?
Something like this:
internal abstract class BaseComparer<T> : IEqualityComparer<T> {
public bool Equals(T x, T y) {
return GetHashCode(x) == GetHashCode(y);
}
public abstract int GetHashCode(T obj);
}
internal class DetailComparer : BaseComparer<StyleFeatureItem> {
public override int GetHashCode(MyClass obj) {
return obj.ID.GetHashCode();
}
}
Usage:
list.Distinct(new DetailComparer())
You can easily query with LINQ like this
considering this JSON
{
"items": [
{
"id": "10",
"name": "one"
},
{
"id": "12",
"name": "two"
}
]
}
putting it in a variable called json like this,
JObject json = JObject.Parse("{'items':[{'id':'10','name':'one'},{'id':'12','name':'two'}]}");
you can select all ids from the items where name is "one" using the following LINQ query
var Ids =
from item in json["items"]
where (string)item["name"] == "one"
select item["id"];
Then, you will have the result in an IEnumerable list

Check IEnumerable<T> for items having duplicate properties

How to check if an IEnumerable has two or more items with the same property value ?
For example a class
public class Item
{
public int Prop1 {get;set;}
public string Prop2 {get;set;}
}
and then a collection of type IEnumerable<Item>
I need to return false if there are items with duplicate values in Prop1.
You want to check only for Prop1 right ?
What about:
IEnumerable<Item> items = ...
var noDistinct = items.GroupBy(x => x.Prop1).All(x => x.Count() == 1);
// it returns true if all items have different Prop1, false otherwise
I think this method will work.
public static bool ContainsDuplicates<T1>(this IEnumerable<T1> source, Func<T1, T2> selector)
{
var d = new HashSet<T2>();
foreach(var t in source)
{
if(!d.Add(selector(t)))
{
return true;
}
}
return false;
}
A short, one-enumeration only solution would be:
public static bool ContainsDuplicates<T>(this IEnumerable<T> list)
=> !list.All(new HashSet<T>().Add);
which could be read as: A list has no duplicates when All items can be Add-ed to a set.
This is conceptually similar to Jake Pearsons solution; however, it leaves out the independant concept of projection; the OP's question would then be solved as:
items.Select(o => o.Prop1).ContainsDuplicates()
bool x = list.Distinct().SequenceEqual(list);
x is true if list has duplicates.
Have you tried Enumerable.Distinct(IEnumerable, IEqualityComparer)?
You can select the distinct values from the IEnumerable and then check the count against that of the full collection.
Example:
var distinctItemCount = myEnumerable.Select(m => m.Prop1).Distinct().Count();
if(distinctItemCount < myEnumerable.Count())
{
return false;
}
This could potentially be made for performant, but it's the only correct answer so far.
// Create an enumeration of the distinct values of Prop1
var propertyCollection = objectCollection.Select(o => o.Prop1).Distinct();
// If the property collection has the same number of entries as the object
// collection, then all properties are distinct. Otherwise there are some
// duplicates.
return propertyCollection.Count() == objectCollection.Count();
public static class EnumerableEx
{
public static IEnumerable<T> GetDuplicates<T>(this IEnumerable<T> source)
{
return source.GroupBy(t => t).Where(x => x.Count() > 1).Select(x => x.Key);
}
}
Personally, I like the neatness of extension methods.
If your objects don't require a selector for determining equality, then this works nicely.
We can remove duplicate entries by using .Distinct() in ArrayList.
Example:
I have a createdby column in testtable with 5 duplicate entries. I have to get only one row
ID Createdby
=== ========
1 Reddy
2 Reddy
3 Reddy
4 Reddy
Considering the above table, I need to select only one "Reddy"
DataTable table=new DataTable("MyTable");//Actually I am getting this table data from database
DataColumn col=new DataColumn("Createdby");
var childrows = table.AsEnumerable().Select( row => row.Field<object>(col)).Distinct().ToArray();

Categories

Resources