2012-03-27 2 views
6

У меня естьLINQ, создавая уникальную коллекцию из коллекции

class Vertex{ 
    Graph _graph; 
    float x; 
    float y; 
    string key; 
    //and some similar atributes 
    public IEnumerable<Edge> Edges{ 
     get{ 
      return _graph.Edges.Where(s => s.Source == this); 
     } 
    } 
} 
class Edge{ 
    Graph _graph; 
    Vertex source; 
    Vertex target; 
} 
class Graph 
{ 
    private VertexCollection _vertexCollection; // extends List<Vertex> 
    private EdgeCollection _edgeCollection; //extends List<Edge> 
    public IEnumerable<Vertex> Vertexes 
    { 
     get 
     { 
      return _vertexCollection; 
     } 
    } 
    public IEnumerable<Edge> Edges 
    { 
     get 
     { 
      return _edgeCollection; 
     } 
    } 
    public IDictionary<Edge, bool> DrawableEdges 
    { 
     get 
     { 
      //want to return my uniq dictionary 
     } 
    }  

Edges и Vertexes собраны в списки

Некоторые примеры:

A-->B // edge from vertex A to B 
B-->C // edge from vertex B to C 
C-->A // edge from vertex C to A 
A-->C // edge from vertex A to C -- this is two way edge 

Так что я хотел бы сделать IDictionary<Edge, bool>, который бы (A -> B и B -> A будет как 1), а bool - если это два пути или нет.

Мне нужно это, потому что, когда я рисую их сейчас, он рисует 2 стрелы друг под друга. Я бы лучше сделал 1 стрелу.

Так что я довольно застрял прямо здесь ... Может кто-нибудь мне немного помочь?

+1

Пожалуйста, покажите определение Края и классы Vertex – sll

ответ

2

Я думаю, вы должны реализовать интерфейс IEquatable для Edge класса:

public class Edge : IEquatable<Edge> 
{ 
    ... 

    public bool Equals(Edge other) 
    { 
     return (
      (other.Source == this.Source && other.Target == this.Target) || 
      (other.Target == this.Source && other.Source == this.Target)); 
    } 

    public override int GetHashCode() 
    { 
     return (Source.GetHashCode()^Target.GetHashCode()); 
    } 
} 

и добавить свои края к HashSet<Edge> коллекции. Затем вы можете вызвать его метод Contains, чтобы проверить, содержит ли он ребро или нет.

EDIT: как сказал Хенк, вы также можете реализовать пользовательские IEqualityComparer класс:

public sealed class EdgeComparer : IEqualityComparer<Edge> 
{ 
    public static EdgeComparer Default { get; private set; } 

    static EdgeComparer() 
    { 
     Default = new EdgeComparer(); 
    } 

    private EdgeComparer() 
    { 
    } 

    public bool Equals(Edge x, Edge y) 
    { 
     return (
      (x.Source == y.Source && x.Target == y.Target) || 
      (x.Target == y.Source && x.Source == y.Target)); 
    } 

    public int GetHashCode(Edge edge) 
    { 
     return (edge.Source.GetHashCode()^edge.Target.GetHashCode()); 
    } 
} 

и инициализировать HashSet с

_drawableEdges = new HashSet<Edge>(EdgeComparer.Default); 
+0

Или напишите отдельный сравнитель, чтобы выполнить ту же логику. Также обеспечивайте симметричный способ комбинирования HashCodes. –

+0

Возможно, вы захотите заменить '==' на 'Equals', чтобы избежать проблем с NaN. И, конечно, OP необходимо реализовать 'Equals',' == ','! = 'И' GetHashCode() ' – CodesInChaos

+1

@HenkHolterman True, я также добавил GetHashCode(). –

2

Я предполагаю, что ваш класс Edge имеет конструктор, который принимает 2 вершины. Ниже приведена возможная идея (я не скомпилировал это, но надеюсь, что вы получите эту идею).

foreach(Edge edge in Edges) 
{ 
    Edge edge2 = new Edge(edge.V2, edge.V1); 
    if (!dict.ContainsKey(edge) && !dict.ContainsKey(edge2)) 
    { 
     dict[edge] = false; // first time we've seen this edge, so put it in dictionary 
    } 
    else if (!dict.ContainsKey(edge) && dict.ContainsKey(edge2)) 
    { 
     dict[edge2] = true; // a bidirectional edge 
    } 
} 
+0

десять секунд быстрее на ничью, чем у меня, есть надпись. –

+0

ye, basicley Мне нужна была просто идея – Wish

Смежные вопросы