【问题标题】:How should I add where condition in lambda expression我应该如何在 lambda 表达式中添加 where 条件
【发布时间】:2017-05-09 11:19:21
【问题描述】:

我知道将 lambda 表达式的位置放在下一行很容易,但由于我是新手,所以我不知道。 在下面的代码中,coupon.products 有大约 27000 种产品,在下面的行中,我必须添加 where 条件,如

where p.id not in (1,2,3) 

int[] productIds = (from p in coupon.Products select p.Id).ToArray<int>();

我应该如何添加另外我应该如何优化我的代码?

我试过了

int[] productIds = (from p in coupon.Products select p.Id).ToArray<int>().Where(i => i.Id not in (1,2));

试过了还是不行

            List<int> excludedItems = new List<int>();
            foreach (BasketItem item in basket.Items)
            {
                excludedItems.Add(item.Product.Id);
            }

            // int[] excluded = new int[] { 1, 2, 3 };

            int[] productIds = coupon.Products.Where(p => excludedItems.Contains(p.Id))
                                              .Select(p => p.Id)
                                              .ToArray();

【问题讨论】:

  • 在 ToArray 之前添加 Where ,我认为它应该可以工作。
  • @TamásSzabó 他们不会在Id 上选择然后在上面调用.Id
  • 没错,那么第二个 lambda 必须是 i =&gt; i not in (1, 2)

标签: c# performance linq lambda


【解决方案1】:

我个人会先Select 获得Ids,然后进一步的操作可能会更快。然后,您可以使用Except 代替Where,最后调用ToArray

int[] excludedIds = new int[] { 1, 2, 3 };
int[] productIds = coupon.Products.Select(p => p.Id)
                                  .Except(excludedIds)
                                  .ToArray();

您的代码的问题来自以下部分:

.ToArray<int>().Where(i => i.Id not in (1,2));

首先,您调用ToArray,然后调用WhereWhere 将返回一个IEnumerable,并且您需要一个数组。其次,您在Idselect,然后在您只需要i 时尝试在Where 中访问它。最后,您可以在需要 !(new int[] { 1, 2 }).Contains(i) 时使用 not in,尽管这样读起来不太好,并且在每次检查时创建数组会很昂贵。


根据您更新的问题Productcommaitems 是一个string,其中包含一个逗号分隔的整数列表。你需要一个int[],你可以使用SplitParse

 int[] excludedItems = Productcommaitems.Split(',')
                                        .Select(Int32.Parse)
                                        .ToArray();

或者更好的是直接创建excludedItems

List<int> excludedItems = new List<int>();
foreach (BasketItem item in basket.Items)
{
    excludedItems.Add(item.Product.Id);
}

【讨论】:

  • 好用Except
  • @PatrickHofman 我也喜欢!Contains,就像你的回答一样,我认为这真的归结为人们会读得更好的情况。
  • 如何将 Productcommaitems 转换为 int[] excludeIds ?
  • @Xtremcool 我已经更新了我的答案,将来只要它们在这种情况下相关,就将您遇到问题的所有代码都包含在minimal reproducible example 中。如果它们不相关,请创建另一个问题。
  • @Xtremcool 自己尝试一下,如果结果不符合您的预期,您可以随时提出新问题并提供minimal reproducible example
【解决方案2】:

如果你想在C#中使用类似SQL的语法,你需要在from之后添加:

int[] excluded = new int[] { 1, 2, 3 };

int[] productIds = (from p in coupon.Products
                    where !excluded.Contains(p.id)
                    select p.Id
                   ).ToArray();

另外,它不是真正的 SQL,所以not in 无效。请改用 C# 等效项 (!Contains)。

当你想使用 LINQ 扩展方法时也是这样:

int[] excluded = new int[] { 1, 2, 3 };

int[] productIds = coupon.Products.Where(p => !excluded.Contains(p.id))
                                  .Select(p => p.id)
                                  .ToArray();

【讨论】:

  • 如何将 Productcommaitems 转换为 int[] excludeIds
  • @Xtremcool 那是一个字符串。那怎么会是一个整数数组?
  • 如何在不循环的情况下将字符串转换为 int[]
  • 如果我创建 1 个 StoreProcedure 并传递排除项目并重新检查其中的项目,然后返回匹配的产品,然后将该值存储在 int[] productIds 中,只需要询问而不是放置此代码.这种情况会减少我的时间吗?现在需要更多时间
【解决方案3】:

你可以试试

int[] array = new int[] { 1, 2, 3 };
int[] ids = coupon.Products.Where(t => !array.Contains(t.id)).Select(t => t.id).ToArray<int>();

【讨论】:

  • 这将返回产品,而不是整数。
  • 另外,调用ToList()是多余的,为什么要先转换成List,再转换成Array,那只是浪费资源。
  • 在每个循环上创建数组很昂贵,您可以使用否定,!,而不是== false&lt;int&gt; 是多余的,ToList 是多余且昂贵的,最后它Select 然后 Where 可能会更快,尽管两者都可以。
【解决方案4】:

你可以像这样使用 C# Linq 语法

int[] filterOut = new int[] {1,2,3};

int[] productIds = coupon.Products.Where(x => !filterOut.Contains(x.Id).Select(x => x.Id).ToArray();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多