https://www.npmjs.com/package/downloads-folder
Использование
const downloadsFolder = require('downloads-folder');
console.log(downloadsFolder());
Установка
$ npm install downloads-folder
Вы можете использовать Linq GroupBy
в модифицированной версии, которая группируется, только если эти два элемента смежны, тогда это легко:
var result = classes
.GroupAdjacent(c => c.Value)
.Select(g => new {
SequenceNumFrom = g.Min(c => c.SequenceNumber),
SequenceNumTo = g.Max(c => c.SequenceNumber),
Value = g.Key
});
foreach (var x in result)
Console.WriteLine("SequenceNumFrom:{0} SequenceNumTo:{1} Value:{2}", x.SequenceNumFrom, x.SequenceNumTo, x.Value);
Результат:
SequenceNumFrom:1 SequenceNumTo:2 Value:9
SequenceNumFrom:3 SequenceNumTo:5 Value:15
SequenceNumFrom:6 SequenceNumTo:6 Value:30
SequenceNumFrom:7 SequenceNumTo:7 Value: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;
}
}
Вы можете использовать этот запрос linq
var values = (new[] { 9, 9, 15, 15, 15, 30, 9 }).Select((x, i) => new { x, i });
var query = from v in values
let firstNonValue = values.Where(v2 => v2.i >= v.i && v2.x != v.x).FirstOrDefault()
let grouping = firstNonValue == null ? int.MaxValue : firstNonValue.i
group v by grouping into v
select new
{
From = v.Min(y => y.i) + 1,
To = v.Max(y => y.i) + 1,
Value = v.Min(y => y.x)
};
Вы можете сделать это следующим образом:
var all = new [] {
new Cls(1, 9)
, new Cls(2, 9)
, new Cls(3, 15)
, new Cls(4, 15)
, new Cls(5, 15)
, new Cls(6, 30)
, new Cls(7, 9)
};
var f = all.First();
var res = all.Skip(1).Aggregate(
new List<Run> {new Run {From = f.SequenceNumber, To = f.SequenceNumber, Value = f.Value} }
, (p, v) => {
if (v.Value == p.Last().Value) {
p.Last().To = v.SequenceNumber;
} else {
p.Add(new Run {From = v.SequenceNumber, To = v.SequenceNumber, Value = v.Value});
}
return p;
});
foreach (var r in res) {
Console.WriteLine("{0} - {1} : {2}", r.From, r.To, r.Value);
}
Идея состоит в том, чтобы творчески использовать Aggregate
: начиная со списка, состоящего из одного Run
, проверьте содержимое списка, до сих пор на каждом этапе агрегации (утверждение if
в лямбда). В зависимости от последнего значения, продолжайте старый запуск или запустите новый.
Вот демон g0 на ideone .
foreach
, когда в лямбда есть такой код.
– juharr
14 February 2013 в 18:38
foreach
.
– Servy
14 February 2013 в 18:42
Я смог выполнить это, создав собственный метод расширения.
static class Extensions {
internal static IEnumerable<Tuple<int, int, int>> GroupAdj(this IEnumerable<Cls> enumerable) {
Cls start = null;
Cls end = null;
int value = Int32.MinValue;
foreach (Cls cls in enumerable) {
if (start == null) {
start = cls;
end = cls;
continue;
}
if (start.Value == cls.Value) {
end = cls;
continue;
}
yield return Tuple.Create(start.SequenceNumber, end.SequenceNumber, start.Value);
start = cls;
end = cls;
}
yield return Tuple.Create(start.SequenceNumber, end.SequenceNumber, start.Value);
}
}
Вот реализация:
static void Main() {
List<Cls> items = new List<Cls> {
new Cls { SequenceNumber = 1, Value = 9 },
new Cls { SequenceNumber = 2, Value = 9 },
new Cls { SequenceNumber = 3, Value = 15 },
new Cls { SequenceNumber = 4, Value = 15 },
new Cls { SequenceNumber = 5, Value = 15 },
new Cls { SequenceNumber = 6, Value = 30 },
new Cls { SequenceNumber = 7, Value = 9 }
};
Console.WriteLine("From To Value");
Console.WriteLine("===== ===== =====");
foreach (var item in items.OrderBy(i => i.SequenceNumber).GroupAdj()) {
Console.WriteLine("{0,-5} {1,-5} {2,-5}", item.Item1, item.Item2, item.Item3);
}
}
И ожидаемый вывод:
From To Value
===== ===== =====
1 2 9
3 5 15
6 6 30
7 7 9
Вот реализация без каких-либо вспомогательных методов:
var grp = 0;
var results =
from i
in
input.Zip(
input.Skip(1).Concat(new [] {input.Last ()}),
(n1, n2) => Tuple.Create(
n1, (n2.Value == n1.Value) ? grp : grp++
)
)
group i by i.Item2 into gp
select new {SequenceNumFrom = gp.Min(x => x.Item1.SequenceNumber),SequenceNumTo = gp.Max(x => x.Item1.SequenceNumber), Value = gp.Min(x => x.Item1.Value)};
Идея такова:
Она называется GroupAdjacent
и реализована как метод расширения на IEnumerable
:
] Группирует смежные элементы последовательности в соответствии с заданной функцией выбора ключа.
blockquote>enumerable.GroupAdjacent(e => e.Key)
Существует даже Nuget «исходный» пакет , который содержит только этот метод, если вы не хотите втягивать дополнительный бинарный пакет Nuget .
Метод возвращает
IEnumerable<IGrouping<TKey, TValue>>
, поэтому его вывод может обрабатываться так же, как и вывод изGroupBy
.
Неверная темная магия. Настоящая версия кажется, что в этом случае было бы легче.
IEnumerable<Cls> data = ...;
var query = data
.GroupBy(x => x.Value)
.Select(g => new
{
Value = g.Key,
Sequences = g
.OrderBy(x => x.SequenceNumber)
.Select((x,i) => new
{
x.SequenceNumber,
OffsetSequenceNumber = x.SequenceNumber - i
})
.GroupBy(x => x.OffsetSequenceNumber)
.Select(g => g
.Select(x => x.SequenceNumber)
.OrderBy(x => x)
.ToList())
.ToList()
})
.SelectMany(x => x.Sequences
.Select(s => new { First = s.First(), Last = s.Last(), x.Value }))
.OrderBy(x => x.First)
.ToList();