我有一个时间间隔列表。时间间隔类型为HistoMesures
。
每个HistoMesure
由Debut
(开始)属性,Fin
(结束)属性和Commentaires
(小注释)属性定义。
我的清单是这样制作的:
HistoMesure
独占,我的意思是他们不能相互重叠。Debut
排序,因此按间隔开始排序。HistoMesure
都是连续的。我想合并(在一个大间隔中转换两个小间隔)所有相邻 HistoMesure
具有相同的Commentaires
。目前我这样做:
//sortedHistos type is List<HistoMesure>
int i = 0;
while (i < sortedHistos.Count - 1)
{
if (sortedHistos[i].Commentaires == sortedHistos[i + 1].Commentaires)
{
sortedHistos[i].Fin = sortedHistos[i + 1].Fin;
sortedHistos.RemoveAt(i + 1);
}
else
{
++i;
}
}
但是我觉得它存在一种更优雅的方式,可能是LINQ。你有什么建议吗?
答案 0 :(得分:3)
你的解决方案运行正常,我会保留它。
如果它不符合您的要求,请不要尝试使用LINQ。 LINQ非常适合编写查询(这是LINQ的Q),修改现有列表并不是那么好。
答案 1 :(得分:2)
此代码将产生重叠的合并间隔。即如果你有间隔A,B,C,其中A和C有相同的注释,结果将是AC,B:
var result = from h in sortedHistos
group h by h.Commentaires into g
select new HistoMesure {
Debut = g.First().Debut, // thus you have sorted entries
Fin = g.Last().Fin,
Commentaires = g.Key
};
如果未对间隔进行排序,则可以使用Min
和Max
。
更新:没有默认的LINQ运算符允许您创建相邻的组。但你总能创造一个。这是IEnumerable<T>
扩展名(我跳过参数检查):
public static IEnumerable<IGrouping<TKey, TElement>> GroupAdjacent<TKey, TElement>(
this IEnumerable<TElement> source, Func<TElement, TKey> keySelector)
{
using (var iterator = source.GetEnumerator())
{
if(!iterator.MoveNext())
{
yield break;
}
else
{
var comparer = Comparer<TKey>.Default;
var group = new Grouping<TKey, TElement>(keySelector(iterator.Current));
group.Add(iterator.Current);
while(iterator.MoveNext())
{
TKey key = keySelector(iterator.Current);
if (comparer.Compare(key, group.Key) != 0)
{
yield return group;
group = new Grouping<TKey, TElement>(key);
}
group.Add(iterator.Current);
}
if (group.Any())
yield return group;
}
}
}
此扩展名创建具有相同键值的相邻元素组。不幸的是,.NET中的所有IGrouping实现都是内部的,所以你需要你的:
public class Grouping<TKey, TElement> : IGrouping<TKey, TElement>
{
private List<TElement> elements = new List<TElement>();
public Grouping(TKey key)
{
Key = key;
}
public TKey Key { get; private set; }
public IEnumerator<TElement> GetEnumerator()
{
return elements.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(TElement element)
{
elements.Add(element);
}
}
现在您的代码将如下所示:
var result = sortedHistos.GroupAdjacent(h => h.Commentaries)
.Select(g => new HistoMesure {
Debut = g.Min(h => h.Debut),
Fin = g.Max(h => h.Fin),
Commentaries = g.Key
});
答案 2 :(得分:1)
使用Linq并从this article借用相邻值进行分组,这应该有效:
您的查询:
var filteredHistos = sortedHistos
.GroupAdjacent(h => h.Commentaires)
.Select(g => new HistoMesure
{
Debut = g.First().Debut,
Fin = g.Last().Fin,
Commentaires = g.Key
});
从文章中复制,其余代码分组为:
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;
}
}
public static class LocalExtensions
{
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);
}
}
答案 3 :(得分:0)
如果我理解正确,你需要这样的东西:
this.node.onaudioprocess = function(e){
if (!recording) return;
var buffer = [];
for (var channel = 0; channel <1; channel++){
buffer.push(e.inputBuffer.getChannelData(channel));
}
worker.postMessage({
command: 'record',
buffer: buffer
});
}