I'm trying to put non duplicated values in a lookup edit using the code below but the variable unique is always null, and I don't know where is the problem.
Any help please?
List<VueItemItemUnit> liste = ObjReservation.LoadAllFamilles();
var unique =
from element in liste
group element by element.FA_CODE into Group
where Group.Count() == 1
select Group.Key;
lookUpFamille.Properties.DataSource = unique;
Try this :
var unique = liste.Distinct(element => element.FA_CODE).Select(element => element.FA_CODE);
I suggest you use the following approach:
lookUpFamille.Properties.DataSource = list.DistinctBy(e => e.FA_CODE).ToList();
//...
// DistinctBy<T,TKey> extension
static class EnumerableHelper {
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector) {
return source.Distinct(new EqualityComparer<T, TKey>(keySelector));
}
class EqualityComparer<T, TKey> : IEqualityComparer<T> {
readonly Func<T, TKey> keySelector;
public EqualityComparer(Func<T, TKey> keySelector) {
this.keySelector = keySelector;
}
bool IEqualityComparer<T>.Equals(T x, T y) {
return Equals(keySelector(x), keySelector(y));
}
int IEqualityComparer<T>.GetHashCode(T obj) {
return keySelector(obj).GetHashCode();
}
}
}
Related
I traced group source code, and found group will new a GroupedEnumerable object. But when I tried below code it can't use is GroupedEnumerable to check.
var orders = new[] {
new {ID=1,Country="US",CreateDate=new DateTime(2021,01,01),PrdtID="P0020",Qty=100,Amount=100},
new {ID=2,Country="US",CreateDate=new DateTime(2021,01,02),PrdtID="P0021",Qty=200,Amount=200},
new {ID=3,Country="US",CreateDate=new DateTime(2021,02,03),PrdtID="P0022",Qty=300,Amount=300},
new {ID=4,Country="US",CreateDate=new DateTime(2021,02,04),PrdtID="P0023",Qty=400,Amount=400},
new {ID=5,Country="CN",CreateDate=new DateTime(2021,01,01),PrdtID="P0020",Qty=100,Amount=100},
new {ID=6,Country="CN",CreateDate=new DateTime(2021,01,02),PrdtID="P0021",Qty=200,Amount=200},
new {ID=7,Country="CN",CreateDate=new DateTime(2021,02,03),PrdtID="P0022",Qty=300,Amount=300},
new {ID=8,Country="CN",CreateDate=new DateTime(2021,02,04),PrdtID="P0023",Qty=400,Amount=400},
};
var query = from order in orders
group order by new { order.CreateDate.Year, order.CreateDate.Month } into g1
from g2 in (
from order in g1
group order by order.Country
)
group g2 by g1.Key;
;
var isGroup = query is System.Linq.GroupedEnumerable;
group source code:
public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return new GroupedEnumerable<TSource, TKey>(source, keySelector, null);
}
public interface IGrouping<out TKey, out TElement> : IEnumerable<TElement>, IEnumerable
{
TKey Key
{
get;
}
}
using System.Collections.Generic;
public GroupedEnumerable(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
if (source == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}
if (keySelector == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keySelector);
}
_source = source;
_keySelector = keySelector;
_comparer = comparer;
}
Why I want to do this
I want to make a helper, check if input object is group value then using specified logic to solve it.
Update:
I found GroupedEnumerable internal sealed class so it can't use is GroupedEnumerable to check
I believe you sould make your helper checking an interface,
e.g. IEnumerable<IGrouping<TKey,TElement>>
I would suggest an extension on that interface
Sample:
static class Extension
{
public static string AmI<TKey, TElement>(this IEnumerable<IGrouping<TKey, TElement>> source)
{
Console.WriteLine(typeof(TKey));
Console.WriteLine(typeof(TElement));
return string.Join(',', source.Select(g => g.Key));
}
}
Here is function and test
[TestMethod]
public void Test()
{
var array = new int[] {1, 2, 3, 4, 5, 6};
var grouping = array.GroupBy(x => x % 2);
IsGrouping(grouping)
.Should()
.BeTrue();
IsGrouping(array)
.Should()
.BeFalse();
}
private bool IsGrouping(IEnumerable someEnumerable)
{
return someEnumerable
.GetType()
.GetInterfaces()
.Any(x => x.IsGenericType
&& typeof(IEnumerable<>) == x.GetGenericTypeDefinition()
&& x.GenericTypeArguments.Length == 1
&& x.GenericTypeArguments.First().IsGenericType
&& x.GenericTypeArguments.First().GetGenericTypeDefinition() == typeof(IGrouping<,>)
);
}
Now I use a bad way checking by name to solve problem.
var isGroup = query.GetType().Name.StartsWith("GroupedEnumerable");
This question already has an answer here:
Generic Type in constructor
(1 answer)
Closed 6 years ago.
I've created a validator that checks an IList<T> for duplicates. I came up with the following implementation:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var bar = new Foo() {Bar = "buzz"};
var list = new List<Foo>() { }; //Foo has a property named Bar of type string
var validator = new Validator<Foo, string>(x => x.Bar); //I have to specify the type of Bar
validator.IsValid(list);
}
}
}
public class Foo
{
public string Bar { get; set; }
}
public class Validator<T, Tkey>
{
private readonly Func<T, Tkey> _keySelector;
public Validator(Func<T, Tkey> keySelector)
{
_keySelector = keySelector;
}
public bool IsValid(IList<T> list)
{
if (list != null && list.Count > 0)
{
if (list.GroupBy(_keySelector).Any(g => g.Count() > 1))
{
return false;
}
}
return true;
}
}
But I don't like how It has to be used: I have to specify the type of Bar during construction.
The question is Can I somehow skip TKey when initializing Validator? Can it somehow be inferred?
You can use a generic extension method, which requires a separate static class. Generic methods can derive the T-types from their parameters.
Here is how:
public static class Extensions
{
public static Validator<T, TKey> GetValidatorFor<T, TKey>(this List<T> list, Func<T, TKey> getter) where T : class
{
return new Validator<T, TKey>(getter);
}
}
and then you can use it like this:
var list = new List<Foo>();
var validator = list.GetValidatorFor(x => x.Bar);
You can use an extension (factory) method to create the validator. The compiler will know how to resolve the types:
public static class SomeStaticClass
{
public static Validator<T,TKey> CreateValidator<T,TKey>(this IEnumerable<T> list, Func<T,TKey> keyselector)
{
return new Validator<T,TKey>(keyselector);
}
}
Now a validator can be created with:
var list = new List<Foo>(); //Foo has a property named Bar of type string
var validator = list.CreateValidator(x => x.Bar); //the compiler can infer T (Foo) through the list and TKey from the returned property inside the lambda
You can use a temporary object to apply currying to the generic parameters:
static class Validator
{
public static ValidatorConstructor<T> Construct<T>() => new ValidatorConstructor<T>();
}
class ValidatorConstructor<T>
{
public Validator<T, TKey> WithSelector<TKey>(Func<T, TKey> selector) => new Validator<T, TKey>(selector);
}
class Validator<T, TKey>
{
public Validator(Func<T, TKey> selector)
{
}
}
Usage:
Validator<Foo, Bar> e = Validator.Construct<Foo>().WithSelector(x => x.Bar);
As I understand it, the LINQ (to enumerable) operator(s) GroupBy will enumerate the whole source sequence before returning the first grouping.
This is not very big data friendly and unnecessary if I know the keys are sorted or if I'm not concerned about having distinct grouping keys.
Is there an operator that I've missed which only groups successive items of the same key and returns a grouping as soon as a new key shows up?
Because I didn't find out how to achieve this with existing functionality I wrote my own operator and called it GroupByUntilChanged. Still would prefer to use framework code.
public static class MyEnumerable
{
/// <summary>
/// Groups SUCCESSIVE elements of a sequence having the same key [...].
/// </summary>
public static IEnumerable<IGrouping<TKey, TElement>> GroupByUntilChanged<TSource, TKey, TElement>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
IEqualityComparer<TKey> comparer)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
if (elementSelector == null) throw new ArgumentNullException(nameof(elementSelector));
return GroupByUntilChangedEnumerator(source, keySelector, elementSelector, comparer ?? EqualityComparer<TKey>.Default);
}
// omitted: 7 more overloads returning GroupByUntilChangedEnumerator
private static IEnumerable<IGrouping<TKey, TElement>> GroupByUntilChangedEnumerator<TSource, TKey, TElement>(
IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
IEqualityComparer<TKey> comparer)
{
using (var e = source.GetEnumerator())
{
if (!e.MoveNext())
yield break;
var grouping = new Grouping<TKey, TElement>(keySelector(e.Current), elementSelector(e.Current));
while (e.MoveNext())
{
var key = keySelector(e.Current);
if (comparer.Equals(grouping.Key, key))
grouping.Add(elementSelector(e.Current));
else
{
yield return grouping;
grouping = new Grouping<TKey, TElement>(key, elementSelector(e.Current));
}
}
yield return grouping;
}
}
/// <summary>
/// <see cref="IGrouping{TKey, TElement}"/> implementation.
/// </summary>
private sealed class Grouping<TKey, TElement> : IGrouping<TKey, TElement>
{
private readonly IList<TElement> _elements;
public Grouping(TKey key, TElement first)
{
Key = key;
_elements = new List<TElement> { first };
}
public TKey Key { get; }
public void Add(TElement next)
{
_elements.Add(next);
}
public IEnumerator<TElement> GetEnumerator()
{
return _elements.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _elements.GetEnumerator();
}
}
}
This is not a standard System.Linq extension. However, I did find it in MoreLinq.MoreEnumerable.GroupAdjacent. In particular, the source is very close to what you have (copying and pasting for posterity):
private static IEnumerable<IGrouping<TKey, TElement>> GroupAdjacentImpl<TSource, TKey, TElement>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
IEqualityComparer<TKey> comparer)
{
Debug.Assert(source != null);
Debug.Assert(keySelector != null);
Debug.Assert(elementSelector != null);
Debug.Assert(comparer != null);
using (var iterator = source.Select(item => new KeyValuePair<TKey, TElement>(keySelector(item), elementSelector(item)))
.GetEnumerator())
{
var group = default(TKey);
var members = (List<TElement>) null;
while (iterator.MoveNext())
{
var item = iterator.Current;
if (members != null && comparer.Equals(group, item.Key))
{
members.Add(item.Value);
}
else
{
if (members != null)
yield return CreateGroupAdjacentGrouping(group, members);
group = item.Key;
members = new List<TElement> { item.Value };
}
}
if (members != null)
yield return CreateGroupAdjacentGrouping(group, members);
}
}
private static Grouping<TKey, TElement> CreateGroupAdjacentGrouping<TKey, TElement>(TKey key, IList<TElement> members)
{
Debug.Assert(members != null);
return Grouping.Create(key, members.IsReadOnly ? members : new ReadOnlyCollection<TElement>(members));
}
static class Grouping
{
public static Grouping<TKey, TElement> Create<TKey, TElement>(TKey key, IEnumerable<TElement> members)
{
return new Grouping<TKey, TElement>(key, members);
}
}
#if !NO_SERIALIZATION_ATTRIBUTES
[Serializable]
#endif
private sealed class Grouping<TKey, TElement> : IGrouping<TKey, TElement>
{
private readonly IEnumerable<TElement> _members;
public Grouping(TKey key, IEnumerable<TElement> members)
{
Debug.Assert(members != null);
Key = key;
_members = members;
}
public TKey Key { get; private set; }
public IEnumerator<TElement> GetEnumerator()
{
return _members.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
While this is not framework code it is still well written and tested code (tests) from a library that I've at least seen used by C# developers I respect.
I know 2 ways to remove doubles from an array of objects that support explicit comparing:
Using HashSet constructor and
Using LINQ's Distinct().
How to remove doubles from array of structs, comparing array members by a single field only? In other words, how to write the predicate, that could be used by Distinct().
Regards,
Well, you could implement IEqualityComparer<T> to pick out that field and use that for equality testing and hashing... or you could use DistinctBy which is in MoreLINQ.
Of course, you don't have to take a dependency on MoreLINQ really - you can implement it very simply:
public static IEnumerable<TSource> DistinctBy<TSource, TKey>
(this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector)
{
// TODO: Implement null argument checking :)
HashSet<TKey> keys = new HashSet<TKey>();
foreach (TSource element in source)
{
if (knownKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
I would probably just loop:
var values = new HashSet<FieldType>();
var newList = new List<ItemType>();
foreach(var item in oldList) {
if(hash.Add(item.TheField)) newList.Add(item);
}
The LINQ answer has been published before. I am copying from Richard Szalay's answer here: Filtering duplicates out of an IEnumerable
public static class EnumerationExtensions
{
public static IEnumerable<TSource> Distinct<TSource,TKey>(
this IEnumerable<TSource> source, Func<TSource,TKey> keySelector)
{
KeyComparer comparer = new KeyComparer(keySelector);
return source.Distinct(comparer);
}
private class KeyComparer<TSource,TKey> : IEqualityComparer<TSource>
{
private Func<TSource,TKey> keySelector;
public DelegatedComparer(Func<TSource,TKey> keySelector)
{
this.keySelector = keySelector;
}
bool IEqualityComparer.Equals(TSource a, TSource b)
{
if (a == null && b == null) return true;
if (a == null || b == null) return false;
return keySelector(a) == keySelector(b);
}
int IEqualityComparer.GetHashCode(TSource obj)
{
return keySelector(obj).GetHashCode();
}
}
}
Which, as Richard says, is used like this:
var distinct = arr.Distinct(x => x.Name);
implement a custom IEqualityComparer<T>
public class MyStructComparer : IEqualityComparer<MyStruct>
{
public bool Equals(MyStruct x, MyStruct y)
{
return x.MyVal.Equals(y.MyVal);
}
public int GetHashCode(MyStruct obj)
{
return obj.MyVal.GetHashCode();
}
}
then
var distincts = myStructList.Distinct(new MyStructComparer());
I hate posting this since it's somewhat subjective, but it feels like there's a better method to do this that I'm just not thinking of.
Sometimes I want to 'distinct' a collection by certain columns/properties but without throwing away other columns (yes, this does lose information, as it becomes arbitrary which values of those other columns you'll end up with).
Note that this extension is less powerful than the Distinct overloads that take an IEqualityComparer<T> since such things could do much more complex comparison logic, but this is all I need for now :)
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> getKeyFunc)
{
return from s in source
group s by getKeyFunc(s) into sourceGroups
select sourceGroups.First();
}
Example usage:
var items = new[]
{
new { A = 1, B = "foo", C = Guid.NewGuid(), },
new { A = 2, B = "foo", C = Guid.NewGuid(), },
new { A = 1, B = "bar", C = Guid.NewGuid(), },
new { A = 2, B = "bar", C = Guid.NewGuid(), },
};
var itemsByA = items.DistinctBy(item => item.A).ToList();
var itemsByB = items.DistinctBy(item => item.B).ToList();
Here you go. I don't think this is massively more efficient than your own version, but it should have a slight edge. It only requires a single pass through the sequence, yielding each item as it goes, rather than needing to group the entire sequence first.
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return source.DistinctBy(keySelector, null);
}
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer)
{
if (source == null)
throw new ArgumentNullException("source");
if (keySelector == null)
throw new ArgumentNullException("keySelector");
return source.DistinctByIterator(keySelector, keyComparer);
}
private static IEnumerable<TSource> DistinctByIterator<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer)
{
var keys = new HashSet<TKey>(keyComparer);
foreach (TSource item in source)
{
if (keys.Add(keySelector(item)))
yield return item;
}
}
I've previously written a generic Func => IEqualityComparer utility class just for the purpose of being able to call overloads of LINQ methods that accept an IEqualityComparer with having to write a custom class each time.
It uses a delegate (just like your example) to supply the comparison semantics. This allows me to use the built-in implementations of the library methods rather than rolling my own - which I presume are more likely to be correct and efficiently implemented.
public static class ComparerExt
{
private class GenericEqualityComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, T, bool> m_CompareFunc;
public GenericEqualityComparer( Func<T,T,bool> compareFunc ) {
m_CompareFunc = compareFunc;
}
public bool Equals(T x, T y) {
return m_CompareFunc(x, y);
}
public int GetHashCode(T obj) {
return obj.GetHashCode(); // don't override hashing semantics
}
}
public static IComparer<T> Compare<T>( Func<T,T,bool> compareFunc ) {
return new GenericEqualityComparer<T>(compareFunc);
}
}
You can use this as so:
var result = list.Distinct( ComparerExt.Compare( (a,b) => { /*whatever*/ } );
I also often throw in a Reverse() method to allow for changing the ordering of operands in the comparison, like so:
private class GenericComparer<T> : IComparer<T>
{
private readonly Func<T, T, int> m_CompareFunc;
public GenericComparer( Func<T,T,int> compareFunc ) {
m_CompareFunc = compareFunc;
}
public int Compare(T x, T y) {
return m_CompareFunc(x, y);
}
}
public static IComparer<T> Reverse<T>( this IComparer<T> comparer )
{
return new GenericComparer<T>((a, b) => comparer.Compare(b, a));
}