Linq 如何删除中间的副本

Linq 如何删除中间的副本,linq,enumerable,Linq,Enumerable,给出如下顺序:- var list = new[] {"1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "5a", "6a", "7a", "7b", "8a"}.Select(x => new { P1 = x.Substring(0,1), P2 = x.Substring(1,1)}); 我想删除“中间”的重复项,以:- var expected = new[] {"1a", "1d", "2a", "3a", "4a", "4b",

给出如下顺序:-

var list = new[] {"1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "5a", "6a", "7a", "7b", "8a"}.Select(x => new { P1 = x.Substring(0,1), P2 = x.Substring(1,1)});
我想删除“中间”的重复项,以:-

var expected = new[] {"1a", "1d", "2a", "3a", "4a", "4b", "5a", "6a", "7a", "7b", "8a"}.Select(x => new { P1 = x.Substring(0, 1), P2 = x.Substring(1, 1) });

因此,任何超过两次的重复都会被剔除。重要的是,我得到了第一个和最后一个副本

对于那些没有聚合并希望在此处使用闭包获得超短答案的用户:

var data = new[] { "1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "1e", "5a", "6a", "7a", "7b", "8a" };
char priorKey = ' ';
int currentIndex = 0;

var result2 = data.GroupBy((x) => x[0] == priorKey ? new { k = x[0], g = currentIndex } : new { k = priorKey = x[0], g = ++currentIndex })
    .Select(i => new[] { i.First(), i.Last() }.Distinct())
    .SelectMany(i => i).ToArray();
@Slai的帽子提示,了解它所基于的代码(我为非连续组问题添加了修复)


下面是如何使用聚合。 我没有测试所有的边缘案例。。。只是你的测试用例

var list = new[] { "1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "5a", "6a", "7a", "7b", "8a" }
           .Aggregate(new { result = new List<string>(), first = "", last = "" },
              (store, given) =>
              {
                var result = store.result;
                var first = store.first;
                var last = store.last;

                 if (first == "")
                  // this is the first one.
                  first = given;
                else
                {
                  if (first[0] == given[0])
                    last = given;
                  else
                  {
                    result.Add(first);
                    if (last != "")
                      result.Add(last);
                    first = given;
                    last = "";
                  }

                }
                 return new { result = result, first = first, last = last }; },
                 (store) => { store.result.Add(store.first); if (store.last != "") store.result.Add(store.last); return store.result; })
           .Select(x => new { P1 = x.Substring(0,1), P2 = x.Substring(1,1)});
var list=new[]{“1a”、“1b”、“1c”、“1d”、“2a”、“3a”、“4a”、“4b”、“5a”、“6a”、“7a”、“7b”、“8a”}
.Aggregate(新的{result=new List(),first=”“,last=”“},
(存储,给定)=>
{
var result=store.result;
var first=store.first;
var last=store.last;
如果(第一个==“”)
//这是第一个。
第一个=给定;
其他的
{
如果(第一个[0]==给定的[0])
最后=给定;
其他的
{
结果。添加(第一);
如果(最后一个!=“”)
结果。添加(最后一个);
第一个=给定;
last=“”;
}
}
返回新的{result=result,first=first,last=last};},
(store)=>{store.result.Add(store.first);if(store.last!=“”)store.result.Add(store.last);return store.result;})
.Select(x=>new{P1=x.Substring(0,1),P2=x.Substring(1,1)});
我创建了一个对象来保存到目前为止的列表以及到目前为止已知的第一个和最后一个列表


然后,我只应用逻辑删除中间的内容。

对于那些没有聚合并希望使用闭包得到超级简短答案的人:

var data = new[] { "1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "1e", "5a", "6a", "7a", "7b", "8a" };
char priorKey = ' ';
int currentIndex = 0;

var result2 = data.GroupBy((x) => x[0] == priorKey ? new { k = x[0], g = currentIndex } : new { k = priorKey = x[0], g = ++currentIndex })
    .Select(i => new[] { i.First(), i.Last() }.Distinct())
    .SelectMany(i => i).ToArray();
@Slai的帽子提示,了解它所基于的代码(我为非连续组问题添加了修复)


下面是如何使用聚合。 我没有测试所有的边缘案例。。。只是你的测试用例

var list = new[] { "1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "5a", "6a", "7a", "7b", "8a" }
           .Aggregate(new { result = new List<string>(), first = "", last = "" },
              (store, given) =>
              {
                var result = store.result;
                var first = store.first;
                var last = store.last;

                 if (first == "")
                  // this is the first one.
                  first = given;
                else
                {
                  if (first[0] == given[0])
                    last = given;
                  else
                  {
                    result.Add(first);
                    if (last != "")
                      result.Add(last);
                    first = given;
                    last = "";
                  }

                }
                 return new { result = result, first = first, last = last }; },
                 (store) => { store.result.Add(store.first); if (store.last != "") store.result.Add(store.last); return store.result; })
           .Select(x => new { P1 = x.Substring(0,1), P2 = x.Substring(1,1)});
var list=new[]{“1a”、“1b”、“1c”、“1d”、“2a”、“3a”、“4a”、“4b”、“5a”、“6a”、“7a”、“7b”、“8a”}
.Aggregate(新的{result=new List(),first=”“,last=”“},
(存储,给定)=>
{
var result=store.result;
var first=store.first;
var last=store.last;
如果(第一个==“”)
//这是第一个。
第一个=给定;
其他的
{
如果(第一个[0]==给定的[0])
最后=给定;
其他的
{
结果。添加(第一);
如果(最后一个!=“”)
结果。添加(最后一个);
第一个=给定;
last=“”;
}
}
返回新的{result=result,first=first,last=last};},
(store)=>{store.result.Add(store.first);if(store.last!=“”)store.result.Add(store.last);return store.result;})
.Select(x=>new{P1=x.Substring(0,1),P2=x.Substring(1,1)});
我创建了一个对象来保存到目前为止的列表以及到目前为止已知的第一个和最后一个列表


然后我只应用逻辑删除中间的内容。

按第一个字符分组,并取每组的第一个和最后一个项目:

var list = "1a 1b 1c 1d 2a 3a 4a 4b 5a 6a 7a 7b 8a".Split();

var result = list.GroupBy(i => i[0])
    .Select(i => new[] { i.First(), i.Last() }.Distinct())
    .SelectMany(i => i).ToArray();

Debug.Print(string.Join("\", \"", result)); 
// { "1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "5a", "6a", "7a", "7b", "8a" }

按第一个字符分组,并取每组的第一项和最后一项:

var list = "1a 1b 1c 1d 2a 3a 4a 4b 5a 6a 7a 7b 8a".Split();

var result = list.GroupBy(i => i[0])
    .Select(i => new[] { i.First(), i.Last() }.Distinct())
    .SelectMany(i => i).ToArray();

Debug.Print(string.Join("\", \"", result)); 
// { "1a", "1b", "1c", "1d", "2a", "3a", "4a", "4b", "5a", "6a", "7a", "7b", "8a" }

您可以使用
GroupBy
,因为它保留了顺序(),或
Aggregate
。您可以使用
GroupBy
,因为它保留了顺序(),或
Aggregate
。您的答案比Hogans更简洁,但不允许重复,例如var list=“1a 1b 1c 1d 2a 4a 4a 4a 4a 1a 5a 6a 7a 7a 8a”。也就是说,我将您的代码与结合使用来实现我的目标。谢谢你的指点,我在想GroupByUntil之类的东西。@user630190我想你说的重复是指“拆分非连续组”。因此,您给出的示例需要同时返回1a 1d和更高版本的1e。@user630190-请参阅我的答案以了解修复方法。您的答案比Hogans更简洁,但不允许重复,例如var list=“1a 1b 1c 1d 2a 3a 4b 1e 5a 7a 7b 8a”。也就是说,我将您的代码与结合使用来实现我的目标。谢谢你的指点,我在想GroupByUntil之类的东西。@user630190我想你说的重复是指“拆分非连续组”。因此,您给出的示例需要同时返回1a 1d和更高版本的1e。@user630190-有关修复方法,请参阅我的答案。