如何从多个相似序列中选择最后一组连锁序列

时间:2012-05-11 02:47:09

标签: c# .net linq collections

我有一个int数组,它是来自多个类似数组的连接数组,所有数组都从1开始。

1,2,3,4 1,2 1,2,3 1,2,

int[] list = { 1, 2, 3, 4, 1, 2, 1, 2, 3, 1, 2 };

我想要达到的目的是得到结果的“最后一组”{1,2}。

尝试

int[] list = { 1, 2, 3, 4, 1, 2, 1, 2, 3, 1, 2 };

List<int> lastSet = new List<int>();
var totalSets = list.Count(x => x == 1);

int encounter = 0;
foreach (var i in list)
{
    if (i == 1)
        encounter += 1;

    if (encounter == totalSets)
        lastSet.Add(i);
}

lastSet.ToList().ForEach(x => Console.WriteLine(x));

有没有更好的方法来使用LINQ实现这一点,可能是SkipWhileGroupByAggregate

4 个答案:

答案 0 :(得分:1)

如果您可以将列表设为实际List<int>,或者如果您不想通过.ToList()创建列表副本,则可以执行以下操作:

var list = new[]{ 1, 2, 3, 4, 1, 2, 1, 2, 3, 1, 2 }.ToList();
var lastSet = list.Skip(list.LastIndexOf(1)).ToList();

否则,Aggregate可以正常工作,但这有点难看:

var lastSet = list.Aggregate(new List<int>{1}, (seed, i) => {
    if(i == 1) {seed.Clear(); }
    seed.Add(i);
    return seed;
})

更新

正如dtb指出的那样,你可以使用Array.LastIndexOf而不是创建一个List:

var list = new[]{ 1, 2, 3, 4, 1, 2, 1, 2, 3, 1, 2 };
var lastSet = list.Skip(Array.LastIndexOf(list, 1)).ToList();

答案 1 :(得分:1)

适用于任何IEnumerable(但速度低于直接List版本)

var sub = list.Reverse<int>()
              .TakeWhile(i => i != 1)
              .Concat(new[]{1})
              .Reverse<int>();

如果您愿意,可以在结果上运行ToArray()

答案 2 :(得分:1)

使用下面的GroupAdjacent Extension Method,您可以将列表拆分为以1开头的序列,然后选择最后一个序列:

var result = list.GroupAdjacent((g, x) => x != 1)
                 .Last()
                 .ToList();

public static IEnumerable<IEnumerable<T>> GroupAdjacent<T>(
    this IEnumerable<T> source, Func<IEnumerable<T>, T, bool> adjacent)
{
    var g = new List<T>();
    foreach (var x in source)
    {
        if (g.Count != 0 && !adjacent(g, x))
        {
            yield return g;
            g = new List<T>();
        }
        g.Add(x);
    }
    yield return g;
}

答案 3 :(得分:1)

LINQ被高估了:

int[] list = { 1, 2, 3, 4, 1, 2, 1, 2, 3, 1, 2 };

int pos = Array.LastIndexOf(list, 1);

int[] result = new int[list.Length - pos];
Array.Copy(list, pos, result, 0, result.Length);

// result == { 1, 2 }

现在可读性提高100%:

int[] list = { 1, 2, 3, 4, 1, 2, 1, 2, 3, 1, 2 };

int[] result = list.Slice(list.LastIndexOf(1));

// result == { 1, 2 }

,其中

static int LastIndexOf<T>(this T[] array, T value)
{
    return Array.LastIndexOf<T>(array, value);
}

static T[] Slice<T>(this T[] array, int offset)
{
    return Slice(array, offset, array.Length - offset);
}

static T[] Slice<T>(this T[] array, int offset, int length)
{
    T[] result = new T[length];
    Array.Copy(array, offset, result, 0, length);
    return result;
}