查询二叉树

时间:2016-08-11 05:23:20

标签: c# linq binary-tree

我有一个Root-Parent-Child二叉树,需要根据几个条件求和并获取子值。我不确定是使用Linq还是遍历树。 Linq查询崩溃(Additional information: Unable to cast object of type 'ID' to type 'Greek'),我不知道如何遍历树并检查每个参数。感谢您提供任何帮助,或链接到网站&书籍增加了我的知识。这link有所帮助,但我仍然陷入困境。

public class Node
{
    public List<Node> Children = new List<Node>();
    public Node Parent = null;

    public Node(Node fromParent = null)
    {
        if (fromParent != null)
        {
            Parent = fromParent;
            fromParent.Children.Add(this);
        }
    }
}

public class ID : Node
{
    public int IdNo;
    public int DealNo;
    public string Strategy;
    public ID(int _ID,int _DealNo,string _Strategy) : base(null)
    {
        IdNo = _ID;
        DealNo = _DealNo;
        Strategy = _Strategy;
    }
}

public class Greek : Node
{
    public string LegOrPos;
    public string GreekType;
    public Greek(string _LegOrPos, string _GreekType, Node fromParent = null) : base(fromParent)
    {
        LegOrPos = _LegOrPos;
        GreekType = _GreekType;
    }
}

public class DataPoint : Node
{
    public int DpNo;
    public double Value;
    public DataPoint(int _DpNo, double _Value, Node fromParent = null) : base(fromParent)
    {
        DpNo = _DpNo;
        Value = _Value;
    }
}


public void SimpleTest()
{
    List<Node> MC = new List<Node>();

    // 1st node
    var oID = new ID(23, 2,"Fly");                  // ID,DealNo,Strategy
    var oGreek = new Greek("Leg", "Delta", oID);    //LegOrPos,GreekType
    var oDP = new DataPoint(14, 0.235, oGreek);     //DpNo,Value
    MC.Add(oID);

    // 2nd node
    oID = new ID(25, 5,"BWB");
    oGreek = new Greek("Leg", "Vega", oID);
    oDP = new DataPoint(16, 0.345, oGreek);
    MC.Add(oID);

    // 3rd node
    oID = new ID(31,2,"Fly");
    oGreek = new Greek("Leg", "Delta", oID);
    oDP = new DataPoint(14, 0.456, oGreek);
    MC.Add(oID);

    // use linq or traverse through tree?

    // get total for several parameters
    var Total = MC.Where(x => ((ID)x).DealNo == 2 && ((ID)x).Strategy == "Fly" && ((Greek)x).GreekType == "Delta" && ((DataPoint)x).DpNo == 14)     // should sum 1st and 3rd nodes
        .SelectMany(x => x.Children)
        .Sum(x => ((DataPoint)x).Value);

    // get specific value
    var Val = Convert.ToDouble(MC.Where(x => ((ID)x).IdNo == 23 && ((Greek)x).GreekType == "Delta" && ((DataPoint)x).DpNo == 14)     // should find 1st node
    .SelectMany(x => x.Children)
    .Select(x => ((DataPoint)x).Value).Single());

    // traverse method
    foreach (var objID in MC)
        {
            if (objID.IdNo == 23)     //compile error-IdNo not found
            {
                foreach (Greek objGreek in objID.Children)
                {
                    if (objGreek.GreekType == "Delta")
                    {
                        foreach (DataPoint objDP in objGreek.Children)
                        {
                            if (objDP.DpNo == 14)
                            {
                                double qVal = objDP.Value;
                            }
                        }
                    }
                }
            }
        }
}

2 个答案:

答案 0 :(得分:1)

你似乎遇到的问题是你的标准是不可能的。

这一行:MC.Where(x => ((ID)x).DealNo == 2 && ((ID)x).Strategy == "Fly" && ((Greek)x).GreekType == "Delta" && ((DataPoint)x).DpNo == 14)。有人说,您希望MC的每个成员同时属于IDGreekDataPoint类型。

根据您的评论,您似乎需要这样:

var query =
    from id in MC.OfType<ID>()
    from greek in id.Children.OfType<Greek>()
    from dp in greek.Children.OfType<DataPoint>()
    group dp.Value by new
    {
        id.DealNo,
        id.Strategy,
        greek.LegOrPos,
        greek.GreekType,
        dp.DpNo
    } into gs
    select new
    {
        gs.Key,
        Value = gs.Sum(),
    };

当我在你的数据上运行时,我得到了这个:

query

答案 1 :(得分:0)

迭代列表的方法很少:

/// regular for
for (int L = 0; L <= MC.Count - 1; L++)
{
    Node oID = MC[L];
    if( oID == null ) continue;

    /// oID is your node that you have added to the list MC 
}

/// foreach
foreach ( var oID in MC.Where(_oID => _oID != null) )
{
    /// oID is your node that you have added to the list MC 
}

无论你走哪条路,我们刚收集到的oID你也可以得到你的孩子节点:

foreach ( Greek oGreek in oID.Children.Where(_oGreek => _oGreek != null) )
{
    /// use oGreeks that you've added to your oID node
    ///

    foreach ( DataPoint oDP in oGreek.Children.Where(_oDP => _oDP != null) )
    {
        /// use oDP's that you've added to your greek node
    }
}