如何编辑列表列表的元素?

时间:2014-07-06 09:26:15

标签: c# linq list

我有一个:

var list = new List<List<MyClass>>();

MyClass

public class MyClass
{
  public double X { set; get; }
  public double Y { set; get; }
  public bool Unique{ set; get; }
}

现在我有一个double xdouble y,我希望找到包含相同X and Y的列表元素,并将Unique字段设置为false。

我已经找到了搜索的例子:

var element = (from sublist in list
               from item in sublist
               where item.X == x && item.Y == y
               select item).FirstOrDefault();

但是如何编辑这个元素?

当然,我可以这样做:

foreach (var myClsList in list)
{
  foreach (var myCls in myClsList )
  {
    if (myCls.X == x && myCls.Y == y)
    {
      myCls.Unique= false;
    }
  }
}

但它看起来不太好。

3 个答案:

答案 0 :(得分:1)

看起来您确实想要按其XY属性分组元素,并在这些组中正确设置Unique属性。以下是一些初步想法:

List<Element> allItems = list.SelectMany(l => l);
var groups = allItems.GroupBy(element => new { X = element.X, Y = element.Y });
foreach (var group in groups) {
    bool unique = group.Count() == 1;
    foreach (var element in group) {
        element.Unique = unique;
    }
}

答案 1 :(得分:0)

似乎很不清楚是否要编辑一个元素,或者是否需要编辑符合特定条件的整个元素。

对于您要做的一个元素:

(from sublist in list
 from item in sublist
 where item.X == x && item.Y == y
 select item).First().Unique = false; //the default item will be null

这很有效,但非常难看。更好:

var element = (from sublist in list
               from item in sublist
               where item.X == x && item.Y == y
               select item).FirstOrDefault();
element.Unique = false;

要更改所有内容,请使用foreach。 Linq不是真正的副作用。它应该是一种副作用结构。在你的情况下,我会这样做:

var query = list.SelectMany(sublist => sublist)
                .Where(item => item.X == x && item.Y == y);
foreach(var myClass in query)
    myClass.Unique = false;

如果您真的想要副作用,并希望以linq风格进行,您可以更好地采用流畅的风格调整您的MyClass,如下所示:

public class MyClass
{
  public double X { set; get; }
  public double Y { set; get; }
  public bool Unique { set; get; }

  public MyClass Duplicate()
  {
    Unique = false;
    return this;
  }
}

// So you call:

var query = list.SelectMany(sublist => sublist)
                .Where(item => item.X == x && item.Y == y)
                .Select(item => item.Duplicate());

答案 2 :(得分:0)

关于整体结构的一些想法:

查看词典&lt;&gt;类。这旨在存储可以通过任意类型访问的项目列表。要在这种情况下使用它:

  • 从班级中移除唯一。
  • 使您的类成为结构,因此它按值而不是引用进行比较(即具有相同X / Y的两个不同的MyClasses被认为是相同的)
  • 使用Dictionary<MyClass, bool>
  • 代替列表

(这里似乎需要文字来创建代码块)

public struct MyClass
{
    public double X { get; set; }
    public double Y { get; set; }
}

var items = new Dictionary<MyClass, Bool>();

items[ new MyClass{ X = 3, Y = 7 } ] = false;
items[ new MyClass{ X = -12, Y = -24 } ] = true;

Assert.IsFalse( items[ new MyClass{ X = 3, Y = 7 } ] );
Assert.IsTrue( items[ new MyClass{ X = -12, Y = -24 } ] );

items[ new MyClass{ X = 3, Y = 7 } ] = true;
Assert.IsTrue( items[ new MyClass{ X = 3, Y = 7 } ] );

阐明字典的工作原理:

  • K是“关键”类型;这是用于标记您存储在字典中的项目的类型,用于将项目放入其中并将项目取出时使用。
  • V是“值”类型;这是您要存储的类型。
  • 您可以使用索引器读取或写入字典:
    • var value = dictionary [key]
    • 字典[key] = value
  • 在某些情况下,字典可能比手动迭代列表更快,因为它在内部可能会使用它喜欢的任何数据结构来搜索匹配,这对于大型数据集来说可能更快。我相信它使用GetHashCode来列出匹配,但在这种情况下这可能并不重要。