查询二叉树
Query a 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;
}
}
}
}
}
}
}
有几种迭代列表的方法:
/// 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
}
}
你的问题似乎是你的标准是不可能的。
走这条线:MC.Where(x => ((ID)x).DealNo == 2 && ((ID)x).Strategy == "Fly" && ((Greek)x).GreekType == "Delta" && ((DataPoint)x).DpNo == 14)
。这有点像你希望 MC
的每个成员同时属于 ID
、Greek
和 DataPoint
类型。
根据您的评论,您似乎需要这个:
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(),
};
当我 运行 根据你的数据我得到这个:
我有一个 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;
}
}
}
}
}
}
}
有几种迭代列表的方法:
/// 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
}
}
你的问题似乎是你的标准是不可能的。
走这条线:MC.Where(x => ((ID)x).DealNo == 2 && ((ID)x).Strategy == "Fly" && ((Greek)x).GreekType == "Delta" && ((DataPoint)x).DpNo == 14)
。这有点像你希望 MC
的每个成员同时属于 ID
、Greek
和 DataPoint
类型。
根据您的评论,您似乎需要这个:
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(),
};
当我 运行 根据你的数据我得到这个: