Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在linq中实现for循环_C#_Visual Studio_Linq - Fatal编程技术网

C# 在linq中实现for循环

C# 在linq中实现for循环,c#,visual-studio,linq,C#,Visual Studio,Linq,我一直在尝试将下面的foreach实现到linq,但我的头脑还没有完全准备好。有谁能给我一些建议,告诉我如何将它改为linq,或者一般来说,如何用linq而不是for循环来思考 class Program { static void Main(string[] args) { List<Sales> S1 = new List<Sales>(); S1.Add(new Sales(1,

我一直在尝试将下面的foreach实现到linq,但我的头脑还没有完全准备好。有谁能给我一些建议,告诉我如何将它改为linq,或者一般来说,如何用linq而不是for循环来思考

class Program
    {
        static void Main(string[] args)
        {
            List<Sales> S1 = new List<Sales>();
            S1.Add(new Sales(1,1,false));
            S1.Add(new Sales(1, 1, false));
            S1.Add(new Sales(2, 2, false));
            S1.Add(new Sales(3, 3, false));
            S1.Add(new Sales(4, 4, false));

            List<Sales> S2 = new List<Sales>();
            S2.Add(new Sales(3, 3, false));
            S2.Add(new Sales(4, 4, false));

            //if S1 Product1 == S2 Product1 and S1 Product2 == S2 Product2 then S1 isSold == true.
            for(int i = 0; i < S2.Count; i++)
            {
                for(int j = 0; j < S1.Count; j++)
                {
                    if(S1[j].Product1 == S2[i].Product1 && S1[j].Product2 == S2[i].Product2)
                    {
                        S1[j].ISSold = true;
                    }
                }
            }
        }
        public class Sales
        {
            public int Product1 { get; set; }
            public int Product2 { get; set; }
            public bool ISSold { get; set; }

            public Sales(int product1, int product2, bool iSSold)
            {
                Product1 = product1;
                Product2 = product2;
                ISSold = iSSold;
            }
        }

    }
}
类程序
{
静态void Main(字符串[]参数)
{
列表S1=新列表();
S1.添加(新销售额(1,1,假));
S1.添加(新销售额(1,1,假));
S1.添加(新销售额(2,2,假));
S1.添加(新销售额(3,3,假));
S1.添加(新销售额(4,4,假));
列表S2=新列表();
S2.增加(新销售额(3,3,假));
S2.增加(新销售额(4,4,假));
//如果S1 Product1==S2 Product1和S1 Product2==S2 Product2,则S1 isSold==true。
对于(int i=0;i
不确定foreach的问题出在哪里,一种方法是:

var result = S1.Select(x =>
 {
     if (S2.Any(s2 => s2.Product1 == x.Product1 && s2.Product2 == x.Product2))
     {
         x.ISSold = true;
     }

     return x;
 });
我的建议是

        S1.Where(x => S2.Any(y => x.Product1 == y.Product1 && x.Product2 == y.Product2))
          .Select(x => x.ISSold = true);
          .ToList();

在Linq查询中产生副作用通常被认为是不好的做法,因此我建议使用

foreach(var item in /*query*/)
  item.IsSold = true;
如果S1和S2在实际用例中可能非常大,那么当前相交它们的方法非常慢-O(n^2),因为它为S1的每个元素迭代整个S2,而其他答案只是将这种糟糕的性能转化为Linq调用语法

Linq有一个用于进行交叉的功能,因此如果S1和S2可能相当大,那么使用它将使您的意图更加清晰,并允许改进大型集合的性能

嵌套的for和if循环可以重写为:

    foreach (Sales item in S1.Intersect(S2, new SalesProductComparer()))
      item.ISSold = true;
。。。如果您定义一个助手类,如

  public class SalesProductComparer : IEqualityComparer<Sales>
  {
    public bool Equals(Sales x, Sales y)
    {
      return x.Product1 == y.Product1 && x.Product2 == y.Product2;
    }
    public int GetHashCode(Sales obj)
    {
      return obj.Product1 + 65537 * obj.Product2;
    }
  }
公共类SalesProductComparer:IEqualityComparer
{
公共布尔等于(销售额x,销售额y)
{
返回x.Product1==y.Product1&&x.Product2==y.Product2;
}
public int GetHashCode(销售对象)
{
返回obj.Product1+65537*obj.Product2;
}
}
GetHashCode函数对于Linq在交叉点查询中的性能至关重要——S1和S2的大多数元素甚至不需要相互比较,因为它们返回不同的哈希代码


在最坏的情况下(例如,有一个GetHashCode(…)函数,它只返回0),它会将S1中的每个项目与S2中的每个项目进行比较,与您当前的代码相同。

这里的问题是,您的结果将只包含
ISSold
设置为true的
Sales
,我认为OP想要一份所有这些的清单。我认为他的意图是让IsSold成为现实。这就是Select中发生的情况。我还添加了ToList以使Select实际执行。我认为如果您使用ForEach而不是Select会更好,只需交换ToList并选择around,然后重命名即可。这也将查询与变异分离。它将迭代S1集合两次,而不是1次。