1

我有一个 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 来实现这一点,也许SkipWhile, GroupBy, Aggregate

4

4 回答 4

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 而不是创建列表:

var list = new[]{ 1, 2, 3, 4, 1, 2, 1, 2, 3, 1, 2 };
var lastSet = list.Skip(Array.LastIndexOf(list, 1)).ToList();
于 2012-05-11T02:54:38.210 回答
1

Works for any IEnumerable (but is slower than direct List versions)

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

Run a ToArray() on the result if you like.

于 2012-05-11T02:57:28.913 回答
1

Using the GroupAdjacent Extension Method below, you can split the list into the sequences beginning with 1 and then take the last sequence:

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

with

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;
}
于 2012-05-11T02:58:31.737 回答
1

LINQ is overrated:

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 }

Now with 100% more readable:

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

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

// result == { 1, 2 }

where

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;
}
于 2012-05-11T03:13:40.993 回答