Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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查询中选择null_C#_Linq - Fatal编程技术网

C# 如果值在上一条记录中,则在linq查询中选择null

C# 如果值在上一条记录中,则在linq查询中选择null,c#,linq,C#,Linq,考虑以下查询: var ds = (from t1 in list1 from t2 in list2 select new {t1.Name, t2.Name} ).ToList(); 这将返回如下内容:(粗略表示) 我想得到的是: Name1, InnerName1 Null, InnerName2 Name2, InnerName1 Null, InnerName2. 意思是,如果列表中已经有t1.Name,我希望t1的其余结果

考虑以下查询:

var ds = (from t1 in list1
          from t2 in list2
          select new {t1.Name, t2.Name}
         ).ToList();
这将返回如下内容:(粗略表示)

我想得到的是:

Name1, InnerName1
Null, InnerName2
Name2, InnerName1
Null, InnerName2.
意思是,如果列表中已经有t1.Name,我希望t1的其余结果为null或空字符串

我已经知道我可以循环使用结果,但我将其用作数据源,并希望基于集合做一些事情


有没有一种方法可以在单个查询中实现这一点?

我认为您需要在这里进行交叉连接。 试试这个

//will get null values for both
    var ds = (from t1 in list1
              join t2 in list2 into t3
              from objt3 in t3.DefaultIfEmpty()
              select new {t1.Name, objt3.Name}
             ).ToList();
编辑:

//will get null values for second list
    var ds = (from t1 in list1
              join t2 in list2 into t3
              from objt3 in t3.DefaultIfEmpty()
              where t1 != null
              select new {t1.Name, objt3.Name}
             ).ToList();
//will get null values for second list
    var ds = (from t1 in list1
              where t1 != null
              join t2 in list2 into t3
              from objt3 in t3.DefaultIfEmpty()
              select new {t1.Name, objt3.Name}
             ).ToList();
更新:

//will get null values for second list
    var ds = (from t1 in list1
              join t2 in list2 into t3
              from objt3 in t3.DefaultIfEmpty()
              where t1 != null
              select new {t1.Name, objt3.Name}
             ).ToList();
//will get null values for second list
    var ds = (from t1 in list1
              where t1 != null
              join t2 in list2 into t3
              from objt3 in t3.DefaultIfEmpty()
              select new {t1.Name, objt3.Name}
             ).ToList();

我想你需要交叉连接。 试试这个

//will get null values for both
    var ds = (from t1 in list1
              join t2 in list2 into t3
              from objt3 in t3.DefaultIfEmpty()
              select new {t1.Name, objt3.Name}
             ).ToList();
编辑:

//will get null values for second list
    var ds = (from t1 in list1
              join t2 in list2 into t3
              from objt3 in t3.DefaultIfEmpty()
              where t1 != null
              select new {t1.Name, objt3.Name}
             ).ToList();
//will get null values for second list
    var ds = (from t1 in list1
              where t1 != null
              join t2 in list2 into t3
              from objt3 in t3.DefaultIfEmpty()
              select new {t1.Name, objt3.Name}
             ).ToList();
更新:

//will get null values for second list
    var ds = (from t1 in list1
              join t2 in list2 into t3
              from objt3 in t3.DefaultIfEmpty()
              where t1 != null
              select new {t1.Name, objt3.Name}
             ).ToList();
//will get null values for second list
    var ds = (from t1 in list1
              where t1 != null
              join t2 in list2 into t3
              from objt3 in t3.DefaultIfEmpty()
              select new {t1.Name, objt3.Name}
             ).ToList();

假设您使用Linq to对象,您可以执行以下操作:

string previous = null;
var results = 
    (from t1 in list1
     from t2 in list2
     select new {
         Name1 = (previous == t1.Name) ? null : (previous = t1.Name), 
         Name2 = t2.Name 
     })
    .ToList();
var result = 
    (from t1 in list1
     select 
       list2.Take(1)
         .Select(t2 => new { Name1 = t1.Name,  Name2 = t2.Name })
         .Concat(list2.Skip(1)
           .Select(t2 => new { Name1 = (string)null, Name2 = t2.Name }))
    .SelectMany(x => x)
    .ToList();
但这取决于副作用,并不是特别优雅。您可能更喜欢以下内容:

string previous = null;
var results = 
    (from t1 in list1
     from t2 in list2
     select new {
         Name1 = (previous == t1.Name) ? null : (previous = t1.Name), 
         Name2 = t2.Name 
     })
    .ToList();
var result = 
    (from t1 in list1
     select 
       list2.Take(1)
         .Select(t2 => new { Name1 = t1.Name,  Name2 = t2.Name })
         .Concat(list2.Skip(1)
           .Select(t2 => new { Name1 = (string)null, Name2 = t2.Name }))
    .SelectMany(x => x)
    .ToList();

假设您使用Linq to对象,您可以执行以下操作:

string previous = null;
var results = 
    (from t1 in list1
     from t2 in list2
     select new {
         Name1 = (previous == t1.Name) ? null : (previous = t1.Name), 
         Name2 = t2.Name 
     })
    .ToList();
var result = 
    (from t1 in list1
     select 
       list2.Take(1)
         .Select(t2 => new { Name1 = t1.Name,  Name2 = t2.Name })
         .Concat(list2.Skip(1)
           .Select(t2 => new { Name1 = (string)null, Name2 = t2.Name }))
    .SelectMany(x => x)
    .ToList();
但这取决于副作用,并不是特别优雅。您可能更喜欢以下内容:

string previous = null;
var results = 
    (from t1 in list1
     from t2 in list2
     select new {
         Name1 = (previous == t1.Name) ? null : (previous = t1.Name), 
         Name2 = t2.Name 
     })
    .ToList();
var result = 
    (from t1 in list1
     select 
       list2.Take(1)
         .Select(t2 => new { Name1 = t1.Name,  Name2 = t2.Name })
         .Concat(list2.Skip(1)
           .Select(t2 => new { Name1 = (string)null, Name2 = t2.Name }))
    .SelectMany(x => x)
    .ToList();

您可以使用下面的方法,它基本上模拟了您试图通过使用
Aggregate
来避免的循环。不幸的是,它不能再使用匿名类,因为我们需要使用
Enumerable.Empty()
来启动聚合:

class Data { public string Name; public string Inner; };

// Test data
var data = new Data[] 
{
    new Data {Name = "Name1", Inner = "InnerName1"},
    new Data {Name = "Name1", Inner = "InnerName2"},
    new Data {Name = "Name2", Inner = "InnerName1"},
    new Data {Name = "Name2", Inner = "InnerName2"}
};

// remove duplicate Names
var filtered = data.Aggregate(
    Enumerable.Empty<Data>(),
    (list, newitem) => list.Concat(new Data[] {new Data {
        Name = (list.Any() && list.Last().Name == newitem.Name)
                ? null : newitem.Name,
        Inner = newitem.Inner
    }}));
类数据{公共字符串名称;公共字符串内部;};
//测试数据
var数据=新数据[]
{
新数据{Name=“Name1”,Inner=“InnerName1”},
新数据{Name=“Name1”,Inner=“InnerName2”},
新数据{Name=“Name2”,Inner=“InnerName1”},
新数据{Name=“Name2”,Inner=“InnerName2”}
};
//删除重复的名称
var filtered=data.Aggregate(
Enumerable.Empty(),
(list,newitem)=>list.Concat(新数据[]{newdata{
Name=(list.Any()&&list.Last().Name==newitem.Name)
?null:newitem.Name,
Inner=newitem.Inner
}}));

您可以使用以下方法,它基本上模拟了您试图通过使用
聚合来避免的循环。不幸的是,它不能再使用匿名类,因为我们需要使用
Enumerable.Empty()
来启动聚合:

class Data { public string Name; public string Inner; };

// Test data
var data = new Data[] 
{
    new Data {Name = "Name1", Inner = "InnerName1"},
    new Data {Name = "Name1", Inner = "InnerName2"},
    new Data {Name = "Name2", Inner = "InnerName1"},
    new Data {Name = "Name2", Inner = "InnerName2"}
};

// remove duplicate Names
var filtered = data.Aggregate(
    Enumerable.Empty<Data>(),
    (list, newitem) => list.Concat(new Data[] {new Data {
        Name = (list.Any() && list.Last().Name == newitem.Name)
                ? null : newitem.Name,
        Inner = newitem.Inner
    }}));
类数据{公共字符串名称;公共字符串内部;};
//测试数据
var数据=新数据[]
{
新数据{Name=“Name1”,Inner=“InnerName1”},
新数据{Name=“Name1”,Inner=“InnerName2”},
新数据{Name=“Name2”,Inner=“InnerName1”},
新数据{Name=“Name2”,Inner=“InnerName2”}
};
//删除重复的名称
var filtered=data.Aggregate(
Enumerable.Empty(),
(list,newitem)=>list.Concat(新数据[]{newdata{
Name=(list.Any()&&list.Last().Name==newitem.Name)
?null:newitem.Name,
Inner=newitem.Inner
}}));

与p.s.w.g.的想法相去甚远,它没有使用查询语法。它避免使用
.First()
并使用
Zip

var listResult = list1.SelectMany(x => (new[] { x, })
  .Concat(Enumerable.Repeat((string)null, int.MaxValue))
  .Zip(list2, (y, z) => new { Name1 = y, Name2 = z, }));

与p.s.w.g.提出的不远,它没有使用查询语法。它避免使用
.First()
并使用
Zip

var listResult = list1.SelectMany(x => (new[] { x, })
  .Concat(Enumerable.Repeat((string)null, int.MaxValue))
  .Zip(list2, (y, z) => new { Name1 = y, Name2 = z, }));

要以不同的方式对待序列中的第一项,您可以使用重载
Select
,它传入一个索引,我们可以将其与零进行比较

这种重载在查询语法中是不可访问的,使用所有方法语法而不是混合和匹配,查询看起来会更好一些

var query = list1.SelectMany(t1 => list2.Select((t2, i) => new
{
    Name1 = i == 0 ? t1.Name : null,
    Name2 = t2.Name
}));

要以不同的方式对待序列中的第一项,您可以使用重载
Select
,它传入一个索引,我们可以将其与零进行比较

这种重载在查询语法中是不可访问的,使用所有方法语法而不是混合和匹配,查询看起来会更好一些

var query = list1.SelectMany(t1 => list2.Select((t2, i) => new
{
    Name1 = i == 0 ? t1.Name : null,
    Name2 = t2.Name
}));

我不会编译第二个查询,尽管我看不出有什么问题。第二个查询中的
进入
给了我一个错误
意外标记
我没有编译第二个查询,尽管我看不出有什么问题。第二个问题中的
进入
给了我一个错误,即
意外标记
,这可能是我的帖子中的一个简单的沟通错误,但我完成了这个答案,我意识到这个查询创建了嵌套的结果。等级制度。但是,我已经有了嵌套的结果,我正在尝试将它们展平。就像报表视图可能看起来一样。这有意义吗?也许我遗漏了什么?@paqogomez:它不应该创建嵌套的结果:
filtered
只是一个
IEnumerable
。当我运行
foreach(过滤中的数据d){Console.WriteLine(d.Name+,“+d.Inner);}
时,我得到的结果正是您在问题中要求的结果。可能会出现混淆,因为我的数据在两个列表中,其中您有一个数据类。所以,也许我已经实现了poorlyth,这可能是我的帖子中的一个简单的沟通错误,但是我仔细研究了这个答案,我意识到这个查询创建了嵌套的结果。等级制度。但是,我已经有了嵌套的结果,我正在尝试将它们展平。就像报表视图可能看起来一样。这有意义吗?也许我遗漏了什么?@paqogomez:它不应该创建嵌套的结果:
filtered
只是一个
IEnumerable
。当我运行
foreach(过滤中的数据d){Console.WriteLine(d.Name+,“+d.Inner);}
时,我得到的结果正是您在问题中要求的结果。可能会出现混淆,因为我的数据在两个列表中,其中您有一个数据类。所以,也许我实现得很差。答案似乎很好,我还在努力实现它。但是,我不知道您如何排除在查询的第一个步骤中使用的
first()
串联中的第一行。@paqogomez噢,我的意思是包含一个
。跳过(1)
;请参阅我的更新答案。在第一个示例中,我认为需要切换真/假条件,以便