从C#中的另一个列表更新一个列表中的项目的最优雅方法是什么?

时间:2012-01-11 02:23:22

标签: c# linq collections

我有2个集合,我有以下代码来遍历一个集合,看看它是否存在于另一个集合中。如果确实存在,则更新该项的属性。

        foreach (var favorite in myFavoriteBooks)
        {
            var book = allBooks.Where(r => r.Name == favorite.Name).FirstOrDefault();

            if (book != null)
            {
                book.IsFavorite = true;
            }
        }

是否有更优雅或更快捷的方式来实现上述代码?

4 个答案:

答案 0 :(得分:5)

您可以在扩展方法语法或LINQ语法中使用Join

扩展方法:

foreach(var favorite in myFavoriteBooks.Join(allBooks, 
                                             f => f.Name, 
                                             a => a.Name, 
                                            (f, a) => a))
{
    a.IsFavorite = true;
}

LINQ:

var favorites = from f in myFavoriteBooks
                join a in allBooks on f.Name equals a.Name
                select a

foreach(var favorite in favorites)
{
    favorite.IsFavorite = true;
}

这些解决方案在功能上是相同的;它们的区别仅在于语法,它们比原始解决方案更快,因为LINQ将在两侧构建哈希表并使用它来匹配而不是扫描原始列表中每个项目的其他列表。

答案 1 :(得分:3)

您可以更轻松地在一个集合中找到与另一个集合Any

匹配的图书
var booksInCommon = allBooks.Where(b => myFavoriteBooks.Any(bi => bi.Name == b.Name));
foreach(book b in booksInCommon)
   b.IsFavorite = true;

或者,如果你不介意“棘手的”代码

allBooks.Where(b => myFavoriteBooks.Any(bi => bi.Name == b.Name)).ToList()
    .ForEach(b => b.IsFavorite = true);

修改

正如Adam Robinson所指出的那样,这是一个O(N 2 )算法,所以如果你的两个藏书都有数千本书并选择加入答案,请避免使用它。

答案 2 :(得分:1)

如果书籍集合存储在带有Name键的字典中,那么这将成为一种简单而高效的操作:

        var myFavoriteBooks = new System.Collections.Generic.Dictionary<string, book>();
        var allBooks = new System.Collections.Generic.Dictionary<string, book>();

        foreach (var bookName in myFavoriteBooks.Keys)
        {
            if (allBooks.ContainsKey(bookName))
            {
                allBooks[bookName].IsFavorite = true;
            }
        }

答案 3 :(得分:0)

var favTitles = new HashSet<string>(favorite.Select(f => f.Name));
//favTitles now a hash-based O(1) name lookup.
foreach(var book in allBooks.Where(b => favTitles.Contains(b.Name)))
  book.IsFavorite = true;