LINQ,创建一个独特的集合集合

时间:2012-03-27 17:18:55

标签: c# linq ienumerable

我有

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
        }
    }    

EdgesVertexes被收集到列表中

一些例子:

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),然后布尔 - 如果它是双向的或不是。< / p>

我需要它,因为当我现在绘制它时,它会在彼此之间绘制两个箭头。我最好制作1支箭头。

所以我非常困在这儿......可能有人帮我一点吗?

2 个答案:

答案 0 :(得分: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
    }
}

答案 1 :(得分: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方法来检查它是否包含边缘。

编辑:像Henk说的那样,你也可以实现一个自定义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);