2017-01-05 36 views
5

Bir C# kitaplığında kod yazarak bir (iki boyutlu) veri kümesi üzerinde clustering veriyi esas alarak veriyi gruplara veya kümelere ayırın. Yararlı olması için, kütüphanenin "genel" veya "özel" verileri alması, kümelendirmesi ve kümelenmiş verileri döndürmesi gerekir. (- Ben koordinatları ile çalışıyorum benim durumumda Lat, Lng olarak) Özel verileri içeri aktarma ve geri gönderme - doğru yaklaşımı arayüzler mi?

Bunu yapmak için, ben onunla ilişkili bir 2D vektör vardır içinde veri kümesindeki her veri geçirilen varsaymak gerekir.

ilk düşüncem jenerik türlerini kullanmak ve iki liste, bir (yani List<T>) jenerik verilerin listesi ve 2D vektörleri Coordinate belirtmek için benim sınıf (yani List<Coordinate>, belirterek aynı uzunluktaki başka geçmesine oldu listelerin birbirine indeksle karşılık geldiği bir lat, lng çifti). Ama bu oldukça sıkıcı çünkü algoritmada bu endeksleri bir şekilde takip etmem gerektiği anlamına geliyor.

Bir sonraki düşünce bir arabirim

public interface IPoint 
{ 
    double Lat { get; set; } 
    double Lng { get; set; } 
} 

tanımlayan inferfaces, kullanımı ve aletleri bu arayüzü geçmek verileri (yani, içinde geçen her bir veri olduğunu varsayalım sağlamak için bir Lat ve Lng).

Ama bu benim için de gerçekten çalışmıyor. C# kitaplığımı bir geçiş ağındaki kümeleri durdurmaya (farklı bir projede) kullanıyorum. Sınıf Stop olarak adlandırılır ve bu sınıf ayrıca bir dış kütüphaneden de gelir, bu yüzden o sınıf için arayüzü uygulayamıyorum. Eğer uygulayan IPoint arayüzünü görebileceğiniz gibi

public class ClusterableStop : GTFS.Entities.Stop, IPoint 
{   

    public ClusterableStop(Stop stop) 
    { 
     Id = stop.Id; 
     Code = stop.Code; 
     Name = stop.Name; 
     Description = stop.Description; 
     Latitude = stop.Latitude; 
     Longitude = stop.Longitude; 
     Zone = stop.Zone; 
     Url = stop.Url; 
     LocationType = stop.LocationType; 
     ParentStation = stop.ParentStation; 
     Timezone = stop.Timezone; 
     WheelchairBoarding = stop.WheelchairBoarding; 
    } 
    public double Lat 
    { 
     get 
     { 
      return this.Latitude; 
     } 
    } 

    public double Lng 
    { 
     get 
     { 
      return this.Longitude; 
     } 
    } 
} 

: Sonra şöyle ClusterableStop adında bir sınıf oluşturulması Stop devralan edildi What did

. Şimdi ClusterableStop için kurucuyu ClusterableStop s veri kümesindeki tüm Stop s dönüştürmek için kullanın, sonra algoritmayı çalıştırın ve sonucu ClusterableStop s olarak alın.

Bu onlar düşmek neyi küme dayalı Stop s şeyler yapmak istiyorum çünkü ne istediğini gerçekten değil. Ben yapamam ben aslında yeni durur, yani ClusterableStop örneği çünkü s !!

Hala ne yapmak istediğimi anlayabiliyorum, ör. Orijinal nesneleri Id ile alabilirim. Ama elbette, bunu başarmanın çok daha zarif bir yolu var mı? Arayüzleri kullanmanın doğru yolu bu mu? Bu kadar basit bir fikir gibi görünüyordu - özel verileri geri almak ve geri almak - ama çok karmaşık olduğu ortaya çıktı.

cevap

2

sen işi yapmak için dizilerini kullanarak düşündünüz mı - bazen bu yepyeni bir sınıf yaratmadan iki sınıf ilişkilendirerek bir yoldur. Nokta üzerinde küme şeydir

List<Tuple<Point, Stop>>

: Sen küpe listesi oluşturabilirsiniz.

3

tüm ihtiyaç 2D dizisinin her bir elemanı için bir (enlem, boylam) çift ilişkilendirmek olduğu için, böyle her biri referans noktası için ortak bir konuma üreten bir temsilci alan bir yöntem, yapabilir:

ClusterList Cluster<T>(IList<T> data, Func<int,Coordinate> getCoordinate) { 
    for (int i = 0 ; i != data.Count ; i++) { 
     T item = data[i]; 
     Coordinate coord = getCoord(i); 
     ... 
    } 
} 

Coordinate'un her bir veri öğesiyle nasıl eşleştirileceğine karar vermek artık arayan kişiye kalmıştır.

Liste konumuna göre ilişkilendirmenin, kullanabileceğiniz tek seçenek olmadığını unutmayın.Başka bir seçenek öğeyi alan bir temsilci geçirmek için kullanılır ve döner onun koordinat: koordinatlar nesnenin kendisi, mevcut olmadığında bu yaklaşım durumlarda, endeks bazlı daha iyidir

ClusterList Cluster<T>(IEnumerable<T> data, Func<T,Coordinate> getCoordinate) { 
    foreach (var item in data) { 
     Coordinate coord = getCoord(item); 
     ... 
    } 
} 

rağmen hash tabanlı konteynerler ile iyi oynamak veya bir IComparable<T> olmalıdır ya T bir ilişkisel konteyner çeşit, tutmak için arayan gerektirir. Birinci yaklaşım T herhangi bir kısıtlama yerleştirir. Senin durumunda

, ikinci yaklaşım tercih edilir:

var clustered = Cluster(
    myListOfStops 
, stop => new Coordinate(stop.Latitude, stop.Longitude) 
);