C# 从列表的公共属性值创建字典<;对象>;
假设我们有一个C# 从列表的公共属性值创建字典<;对象>;,c#,linq,list,dictionary,C#,Linq,List,Dictionary,假设我们有一个\u2dline对象列表 public class _2DLine { public double X1 { get; set; } public double Y1 { get; set; } public double X2 { get; set; } public double Y2 { get; set; } } var L1 = new _2DLine { X1 = 0, Y1 = 0, X2 = 100, Y2 = 100 }; var
\u2dline
对象列表
public class _2DLine
{
public double X1 { get; set; }
public double Y1 { get; set; }
public double X2 { get; set; }
public double Y2 { get; set; }
}
var L1 = new _2DLine { X1 = 0, Y1 = 0, X2 = 100, Y2 = 100 };
var L2 = new _2DLine { X1 = 50, Y1 = 50, X2 = 200, Y2 = 200 };
var L3 = new _2DLine { X1 = 0, Y1 = 0, X2 = 200, Y2 = 200};
var L4 = new _2DLine { X1 = 100, Y1 = 100, X2 = 50, Y2 = 50};
var MyLines = new List<_2DLine>
{
L1,
L2,
L3,
L4
}
最终结果如下:
Key | Value
-----------------------------------
_2DPoint(0,0) | { L1, L3 }
_2DPoint(100,100) | { L1, L4 }
_2DPoint(50,50) | { L2, L4 }
_2DPoint(200,200) | { L2, L3 }
将线投影到点和线的展平序列,然后按点分组序列(我使用匿名类型,因为它们实现了Equals和GetHashCode),并创建字典:
var result = MyLines.SelectMany(l => new[] {
new { X = l.X1, Y = l.Y1 },
new { X = l.X2, Y = l.Y2 }
}, (l,p) => new { Point = p, Line = l })
.GroupBy(x => x.Point)
.ToDictionary(g => new _2DPoint { X = g.Key.X, Y = g.Key.Y },
g => g.Select(x => x.Line).ToList());
建议-使用点作为线的起点和终点,而不是四个坐标。还可以改进命名。不要从下划线开始类名,对局部变量使用camelCase名称。例如
public class Line
{
public Line(double startX, double startY, double endX, double endY)
: this(new Point(startX, startY), new Point(endX, endY))
{
}
public Line(Point start, Point end)
{
Start = start;
End = end;
}
public Point Start { get; private set; }
public Point End { get; private set; }
}
我还将创建point作为value对象,并重写Equals和GetHashCode方法,以按值比较点:
public class Point
{
public Point(double x, double y)
{
X = x;
Y = y;
}
public double X { get; private set; }
public double Y { get; private set; }
public override bool Equals(object obj)
{
Point other = obj as Point;
if (other == null)
return false;
return X == other.X && Y == other.Y;
}
public override int GetHashCode()
{
return X.GetHashCode() * 19 + Y.GetHashCode();
}
}
现在,创建行列表如下所示:
var lines = new List<Line> {
new Line(0, 0, 100, 100),
new Line(50, 50, 200, 200),
new Line(0, 0, 200, 200),
new Line(100, 100, 50, 50)
};
这似乎是一个简单的要求。是什么阻碍了你的解决方案?我看这里没有问题。@user414076我不知道如何创建字典。@Vahid:指定该过程的哪个步骤比较困难。创建字典?指定字典的内容?过滤输入集以确定进入字典的内容?是代码给了您一个问题,还是算法?如果让我来推断,我想你脑子里没有一个好的算法。但也许是密码。我不知道,因为你还没有问任何问题。@Vahid我更新了答案,并对查询提出了一些意见和改进代码的建议:)哇,Sergey,这正是我想要的解决方案。这里有一些非常出色的家伙。非常感谢您的更新,WPF中的
行
确实干扰了行
,这就是我选择\u 2DLine
的原因。对于其他类,正如你所说,我使用的是camelCase。
var lines = new List<Line> {
new Line(0, 0, 100, 100),
new Line(50, 50, 200, 200),
new Line(0, 0, 200, 200),
new Line(100, 100, 50, 50)
};
var points = lines.SelectMany(l => new[] { l.Start, l.End },
(l, p) => new { Line = l, Point = p })
.GroupBy(x => x.Point)
.ToDictionary(g => g.Key, g => g.Select(x => x.Line).ToList());