30 Kasım 2016 Çarşamba

Linq Set Metodları

Giriş
Set metodları iki kümeyi belirtilen koşula göre işleyerek bir sonuç seti verirler. Kümedeki işlemi yapabilmek için elemanların denk olup olmadıklarını anlamamız gerekir. Bunun için 3 yöntem var.
1. IEquatable arayüzünü gerçekleştirmek
2. Nesnenin Equals ve GetHashCode metodlarını override etmek
3. Linq metoduna IEqualityComparer nesnesi vermek

1. IEquatable
IEquatable Arayüzü yazısına taşıdım.

2. Nesnenin Equals ve GetHashCode metodlarını override etmek
Bir diğer yöntem ise Object ata sınıfından gelen Equals ve GetHashCode metodlarını override etmek. Kolay bir yöntem şöyle
public class Point2D<T>
{
  public readonly T x;
  public readonly T y;

  public Point2D(T x, T y)
  {
    this.x = x;
    this.y = y;
  }
  public override bool Equals(object obj)
  {
    if (ReferenceEquals(null, obj)) return false;
    if (ReferenceEquals(this, obj)) return true;
    if (obj.GetType() != this.GetType()) return false;
    return Equals((Point2D<T>) obj);
  }

  protected bool Equals(Point2D<T> other)
  {
    return EqualityComparer<T>.Default.Equals(x, other.x) && 
           EqualityComparer<T>.Default.Equals(y, other.y);
  }

  public override int GetHashCode()
  {
    unchecked
    {
      return (EqualityComparer<T>.Default.GetHashCode(x)*397) ^ 
              EqualityComparer<T>.Default.GetHashCode(y);
    }
  }
}

Distinct
Nesnemizin IEquatable arayüzünü gerçekleştirmesi gerekir. Liste sırasyı korumaz.
Örnek
Şöyle yaparız.
list = list.Distinct().ToList();

Except
First ve second olarak isimlendirilen iki küme ile çalışır. First içinde bulunan ama second içinde bulunmaya elemanları döner. SQL ile kullanılan left outer join'e benziyor. Dikkat edilmesi gereken nokta sonuç kümesinde aynı değere sahip birden fazla aynı eleman olmaz! First = {2,2,3} Second = {3} olsaydı fark kümesinin {2,2} olmasını beklerdik. Ancak sonuç sadece {2}'dir. Bu metod Java'daki Set sınıfının Set#removeAll() metoduna benziyor.

Intersect
İki kümenin kesişimini verir. Önce ilk dizinin tekil (distinct) alt kümesi alınır. Daha sonra ikinci dizi ile kesişimini bulunur.
Mesela birinci listede "1","2","2" olsun. İkinci listede ise "1","3" olsun. Listelerin kesişimi sonucu sadece "1"'dir.
When the object returned by this method is enumerated, Intersect enumerates first, collecting all distinct elements of that sequence. It then enumerates second, marking those elements that occur in both sequences. Finally, the marked elements are yielded in the order in which they were collected.

Dizi için şöyle yaparız.
int[] array1 = new int[] { 4, 8, 2, 5, 9, 3 };
int[] array2 = new int[] { 5, 8, 4, 2 };


array2 = array1.Intersect(array2).ToArray();
Çıktı olarak 4,8,2,5 alırız.

Liste için şöyle yaparız.
var list1 = new List<MyClass>() {...};

var list2 = new List<MyClass>() {...};

var alist = list1.Intersect(list2).ToList();
Union
Union iki listeyi birleştirirken çift elemanları sonuca dahil etmez. Sonuç tekil elemanlardan oluşur.
An IEnumerable<T> that contains the elements from both input sequences, excluding duplicates.
Eğer iki listeyi olduğu gibi birleştirmek istersek Concat() metodunu kullanmak gerekir.



Hiç yorum yok:

Yorum Gönder