?
var trimmedItems = items.Reverse().SkipWhile(e => !e.Any()).Reverse();
, , , , .
juharr , :
var trimmedItems = items.Take(items.Reverse().TakeWhile(e => !e.Any()).Count());
, . LINQPad, result.Dump(); -, . , IEnumerable<string> IEnumerable<IEnumerable<string>> , :
void Main()
{
var items = new[] { "a, b, c",
"",
"a, f, g, h",
"",
""}.AsEnumerable();
var manyitems = Enumerable.Range(1, 10000).SelectMany(i => items);
var actions = new[]
{
new TimedAction("Control", () =>
{
manyitems.ToList();
}),
new TimedAction("Reverse().SkipWhile().Reverse()", () =>
{
manyitems.Reverse().SkipWhile(e => !e.Any()).Reverse().ToList();
}),
new TimedAction("Take(Reverse().TakeWhile().Count())", () =>
{
manyitems.Take(manyitems.Reverse().TakeWhile(e => !e.Any()).Count()).ToList();
}),
new TimedAction("SkipLastWhile", () =>
{
manyitems.SkipLastWhile(e => !e.Any()).ToList();
}),
};
const int TimesToRun = 100;
TimeActions(TimesToRun, actions);
}
public static class EnumerableExtensions
{
public static IEnumerable<T> SkipLastWhile<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
var skipBuffer = new List<T>();
foreach (var item in source)
{
if (predicate(item))
skipBuffer.Add(item);
else
{
foreach (var skipped in skipBuffer)
yield return skipped;
skipBuffer.Clear();
yield return item;
}
}
}
}
#region timer helper methods
public void TimeActions(int iterations, params TimedAction[] actions)
{
Stopwatch s = new Stopwatch();
int length = actions.Length;
var results = new ActionResult[actions.Length];
for (int i = 0; i < length; i++)
{
var action = actions[i];
var result = results[i] = new ActionResult { Message = action.Message };
result.DryRun1 = s.Time(action.Action, 10);
result.FullRun1 = s.Time(action.Action, iterations);
}
for (int i = length - 1; i >= 0; i--)
{
var action = actions[i];
var result = results[i];
result.DryRun2 = s.Time(action.Action, 10);
result.FullRun2 = s.Time(action.Action, iterations);
}
results.Dump();
}
public class ActionResult
{
public string Message { get; set; }
public double DryRun1 { get; set; }
public double DryRun2 { get; set; }
public double FullRun1 { get; set; }
public double FullRun2 { get; set; }
}
public class TimedAction
{
public TimedAction(string message, Action action)
{
Message = message;
Action = action;
}
public string Message { get; private set; }
public Action Action { get; private set; }
}
public static class StopwatchExtensions
{
public static double Time(this Stopwatch sw, Action action, int iterations)
{
sw.Restart();
for (int i = 0; i < iterations; i++)
{
action();
}
sw.Stop();
return sw.Elapsed.TotalMilliseconds;
}
}
#endregion
:

, IEnumerable , LINQ Reverse():
var manyitems = Enumerable.Range(1, 10000).SelectMany(i => items).ToList().AsEnumerable();
