我有一个像这样的数据表:
Id Name State
1 xx CA
2 xx NY
3 xx NY
4 xx NY
5 xx NY
6 xx CA
7 xx CA
8 xx NY
9 xx NY
我想知道是否有一个linq语句,我可以创建,在这种情况下,我返回值的范围(开始和结束),在这种情况下是一个状态。 例如Linq query = where(state ==“NY”)并返回2,5和7,9的出现
答案 0 :(得分:1)
您可以使用此扩展程序对连续元素进行分组:
var result = dt.AsEnumerable()
.GroupAdjacent(r => r.Field<string>("State"))
.Where(g => g.Key == "NY")
.Select(g => new{ Min=g.Min(r => r.Field<int>("Id")), Max=g.Max(r => r.Field<int>("Id")) })
.ToList();
foreach (var x in result)
Console.WriteLine("Min={0} Max={1}", x.Min, x.Max);
// Min=2 Max=5
// Min=8 Max=9
这是扩展名:
public static IEnumerable<IGrouping<TKey, TSource>> GroupAdjacent<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector)
{
TKey last = default(TKey);
bool haveLast = false;
List<TSource> list = new List<TSource>();
foreach (TSource s in source)
{
TKey k = keySelector(s);
if (haveLast)
{
if (!k.Equals(last))
{
yield return new GroupOfAdjacent<TSource, TKey>(list, last);
list = new List<TSource>();
list.Add(s);
last = k;
}
else
{
list.Add(s);
last = k;
}
}
else
{
list.Add(s);
last = k;
haveLast = true;
}
}
if (haveLast)
yield return new GroupOfAdjacent<TSource, TKey>(list, last);
}
public class GroupOfAdjacent<TSource, TKey> : IEnumerable<TSource>, IGrouping<TKey, TSource>
{
public TKey Key { get; set; }
private List<TSource> GroupList { get; set; }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return ((System.Collections.Generic.IEnumerable<TSource>)this).GetEnumerator();
}
System.Collections.Generic.IEnumerator<TSource> System.Collections.Generic.IEnumerable<TSource>.GetEnumerator()
{
foreach (var s in GroupList)
yield return s;
}
public GroupOfAdjacent(List<TSource> source, TKey key)
{
GroupList = source;
Key = key;
}
}
编辑:“我很抱歉,而不是使用id可以使用数据表的行索引”
是的,您可以使用投射索引的Select
重载:
var result = dt.AsEnumerable()
.Select((r, index) => new{ Row=r, Index=index })
.GroupAdjacent(x => x.Row.Field<string>("State"))
.Where(g => g.Key=="NY")
.Select(g => new{ Min=g.Min(x => x.Index), Max=g.Max(x => x.Index) })
.ToList();
答案 1 :(得分:0)
按照this answer中提出的逻辑,我想出了一些代码,可以帮到你:
注意为了时间的缘故,我创建了一个包含3个属性的类的列表,但是从DataTable中提取它应该几乎相同....
var newlist1 = (MyList.Where(li => li.State == "NY")
.OrderBy(li => li.Id)
.Select((li, idx) => new {itm = li, val = li.Id - idx})
.GroupBy(nw => nw.val)
.Select(g => new { Min = g.Min(nw => nw.itm.Id),
Max = g.Max(nw => nw.itm.Id)})
).ToList();
在排序结果之后,使这项工作的部分是val
子句中的GroupBy
- 实际上,由于数据是有序的,我们正在减去有序中每个元素的索引来自id的列表 - 所有顺序的元素将获得相同的val
,因此将属于同一组。您需要做的就是,对于每个组,获得最大id
和最小id
,您就完成了。
希望这可以为您提供所需的信息。