使用LINQ

时间:2018-07-12 08:43:04

标签: c# .net linq

我有两个对象列表:

客户和员工

我需要检查是否至少有1位与员工同名的客户。

目前,我有:

client.ForEach(a =>
            {
                if (employee.Any(m => m.Name == a.Name && m.FirstName==a.FirstName)
                {
                    // OK TRUE
                }
            });

我可以通过其他方式改善阅读吗?

2 个答案:

答案 0 :(得分:2)

您为什么不先手动使用连接进行检查?

var mergedClients = Client.Join(listSFull,
                x => new { x.Name, x.FirstName},
                y => new { Name = y.Name, FirstName= y.FirstName},
                (x, y) => new { x, y }).ToList();

然后遍历新集合:

mergedClients.ForEach(a =>
//your logic

此方法的唯一缺点(如果让您感到困扰)是将不包含空值。

答案 1 :(得分:1)

我要么选择加入

using DataFramesMeta
# I generate a smaller DataFrame with cutoff of 15 for the example
df = DataFrame(x1=repeat([1,1,2,2,3], inner=10), x2=rand(50))

# first way to do it
@linq df |>
    groupby(:x1) |>
    where(length(:x1)>15) |>
    @based_on(x2=mean(:x2))

# other way to do the same
@linq df |>
    by(:x1, x2=mean(:x2), n=length(:x2)) |>
    where(:n.>15) |>
    select(:x1, :x2)

或相交

var isDuplicated = clients.Join(employees, 
       c => new { c.Name, c.FirstName }, 
       e => new { e.Name, e.FirstName },
       (c, e) => new { c, e })
       .Any();

var clientNames = clients.Select(c => new { c.Name, c.FirstName }); var employeeNames = employees.Select(e => new { e.Name, e.FirstName }); var isDuplicated = clientNames.Intersect(employeeNames).Any(); Join都使用散列,并且都接近O(n)。

注意:匿名对象(Intersect)的相等性(和哈希码)与值类型相同。即当两个匿名对象的所有字段都相等时,它们是相等的(意味着具有相同的哈希码)。

===编辑:好的,我很感兴趣(希望您的问题与性能有关:P)

new { , }

输出:

[TestMethod]
public void PerformanceTest()
{
    var random = new Random();
    var clients = Enumerable.Range(0, 10000)
            .Select(_ => new Person { FirstName = $"{random.Next()}",      
                                      LastName = $"{random.Next()}" })
            .ToList();

    var employees = Enumerable.Range(0, 10000)
            .Select(_ => new Person { FirstName = $"{random.Next()}", 
                                      LastName = $"{random.Next()}" })
            .ToList();

    var joinElapsedMs = MeasureAverageElapsedMs(() =>
        {
            var isDuplicated = clients.Join(employees,
                    c => new { c.FirstName, c.LastName },
                    e => new { e.FirstName, e.LastName },
                    (c, e) => new { c, e })
                    .Any();
        });

    var intersectElapsedMs = MeasureAverageElapsedMs(() =>
        {
            var clientNames = clients.Select(c => new { c.FirstName, c.LastName });
            var employeeNames = employees.Select(e => new { e.FirstName, e.LastName });
            var isDuplicated = clientNames.Intersect(employeeNames).Any();
        });

    var anyAnyElapsedMs = MeasureAverageElapsedMs(() =>
        {
            var isDuplicated = clients.Any(c => employees.Any(
                    e => c.FirstName == e.FirstName && c.LastName == e.LastName));
        });

    Console.WriteLine($"{nameof(joinElapsedMs)}: {joinElapsedMs}");
    Console.WriteLine($"{nameof(intersectElapsedMs)}: {intersectElapsedMs}");
    Console.WriteLine($"{nameof(anyAnyElapsedMs)}: {anyAnyElapsedMs}");
}

private static double MeasureAverageElapsedMs(Action action) =>
    Enumerable.Range(0, 10).Select(_ => MeasureElapsedMs(action)).Average();

private static long MeasureElapsedMs(Action action)
{
    var stopWatch = Stopwatch.StartNew();
    action();
    return stopWatch.ElapsedMilliseconds;
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

注意:任何一个都为O(n ^ 2)-(在最坏的情况下)每个迭代的客户都会迭代每个员工。