【问题标题】:Get items from a list by ids of another list通过另一个列表的 id 从列表中获取项目
【发布时间】:2017-01-03 21:29:05
【问题描述】:

对不起,如果问题标题令人困惑,我有一个场景,我有两个类用户和地址。

public class User
{
    public int userId { get; set; }
    public string userName { get; set; }

    public List<Address> address { get; set; }
}

public class Address
{
    public string AddressLine { get; set; }
    public string City { get; set; }
    public string State { get; set; }

    public int UserId { get; set; }
}

UserId 是类地址中的外键,我有两个列表,用户列表和地址列表。用户中地址的值为空,我想获取每个用户的地址列表,我该如何实现?我知道我们可以使用 foreach,但是有没有办法通过 linq 来实现呢?下面是示例代码。

class Program
{
    static void Main(string[] args)
    {
        var users = new List<User>();
        users.Add(new User { userId = 1, userName = "User 1" });
        users.Add(new User { userId = 2, userName = "User 2" });
        users.Add(new User { userId = 3, userName = "User 3" });
        users.Add(new User { userId = 4, userName = "User 4" });

        var address = new List<Address>();
        address.Add(new Address { AddressLine = "Address 1", City = "City 1", State = "State 1", UserId = 1 });
        address.Add(new Address { AddressLine = "Address 1 Dup", City = "City 1", State = "State 1", UserId = 1 });
        address.Add(new Address { AddressLine = "Address 2", City = "City 2", State = "State 2", UserId = 2 });
        address.Add(new Address { AddressLine = "Address 2 Dup", City = "City 2", State = "State 2", UserId = 2 });
        address.Add(new Address { AddressLine = "Address 3", City = "City 3", State = "State 3", UserId = 3 });
        address.Add(new Address { AddressLine = "Address 3 Dup", City = "City 3", State = "State 3", UserId = 3 });


    }
}

【问题讨论】:

  • 只是关于您的架构的注释...如果可能,我会考虑修改它。使用地址存储用户 ID 是一个糟糕的设计。如果两个用户住在同一个地址怎么办?你真的应该有一个多对多的关系,即存储一个带有用户 ID 和地址 ID 的中间表。
  • 这只是一个例子,因为我无法发布我的原始代码。这将是安全漏洞,所以我创建了类似的虚拟数据。我同意这种架构设计是错误的。
  • LINQ 也使用 foreach。 check here
  • 简单的GroupJoin 将产生所需的相关性。

标签: c# linq


【解决方案1】:

Linq版本

List<User> result = users.Select(x => 
                         new User() { 
                            userId = x.userId, 
                            userName = x.userName, 
                            address = address.Where(y => y.UserId == x.userId).ToList() 
                         }).ToList();

imo 更易读foreach 版本

foreach (User user in users)
    user.address = address.Where(y => y.UserId == user.userId).ToList();

【讨论】:

  • 谢谢你的回答,对不起,如果这是一个愚蠢的问题,但如果我使用 linq foreach 代替选择它会更慢还是更快? Select 和 Linq Foreach 哪个更好?像这样 users.ForEach(t => t.address = address.Where(a => a.UserId == t.userId).ToList());
  • 这会更快也请注意。它会创建User 的副本,因此对派生列表中每个User 的每次更改都不会影响实际的User。这可能是也可能不是你想要的。使用linq 总是比较慢。
  • 你的意思是选择会更快?我可以更改实际用户,因为这是要求。
  • @ManishMakkad 在这种情况下没关系,这不会是瓶颈 - 选择对你来说更具可读性的代码
  • foreach 总是更快,因为编译器可以轻松优化它。 linq 创建的状态机可能不会那么快,但除非您对数十亿个对象进行操作,否则它不会产生任何影响。我们在这里谈论小纳秒或其他东西。不过,在这种情况下,我会选择Select,只是为了便于阅读。
【解决方案2】:

SelectWhere 相当简单。

users = users.Select(u => { u.address = address.Where(a => a.UserId == u.userId).ToList(); return u; }).ToList();

更易读的版本:

    users = users.Select(u =>
    {
        u.address = address.Where(a => a.UserId == u.userId).ToList();

        return u;
    }).ToList();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-09
    • 2015-03-23
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多