如何在最后记录中包含包含,如果在LINQ中找到



我有一个字符串列表,例如

AAPL,28/03/2012,88.34,88.778,87.187,88.231,163682382
AAPL,29/03/2012,87.54,88.08,86.747,87.123,151551216
FB,30/03/2012,86.967,87.223,85.42,85.65,182255227

现在,我只想使用Linq。

下面我写了包含多行的代码,但我想制作单行代码,

fileLines = System.IO.File.ReadAllLines(fileName).AsParallel().Skip(1).ToList();
var lastLine = fileLines.Last();
if (!lastLine.Contains(item.sym))
{
    fileLines.RemoveAt(fileLines.Count - 1);
}

那么,如何将其全部在单行linq查询中进行?

您可以使用三元操作员来决定尾巴的尾巴,如下所示。

fileLines
    = fileLines.Take(fileLines.Count())
               .Concat(fileLines.Last().Contains(item.sym) ? Enumerable.Empty
                                                           : new string[]{ item.sym });

您可以按以下方式提出更多收缩。

fileLines
    = System.IO.File.ReadAllLines(fileName)
                    .AsParallel()
                    .Skip(1)
                    .Take(fileLines.Count())
                    .Concat(fileLines.Last().Contains(item.sym) ? Enumerable.Empty
                                                                : new string[]{ item.sym });
                    .ToList();

话虽如此,这样的努力是值得怀疑的。懒惰评估的LINQ扩展方法的积累很难进行调试。

我知道您需要简化过滤操作,从我的情况下,您只缺少一条信息(即当前项目是否是最后一项枚举集合中的一个)将帮助您定义谓词。我现在要写的东西似乎不是"简单的单行"。但是,这将是可重复使用的扩展程序,它将在不执行额外和不必要的循环或迭代的情况下提供此信息(以及更多)。

最终产品将是:

IEnumerable<string> fileLines = System.IO.File.ReadLines(fileName).RichWhere((item, originalIndex, countedIndex, hasMoreItems) => hasMoreItems || item.StartsWith("AAPL"));

我写的类似于Linq的扩展名,灵感来自Microsoft在Referencesource中枚举的启发:

public delegate bool RichPredicate<T>(T item, int originalIndex, int countedIndex, bool hasMoreItems);
public static class EnumerableExtensions
{
    /// <remarks>
    /// This was contributed by Aly El-Haddad as an answer to this Stackoverflow.com question:
    /// https://stackoverflow.com/q/54829095/3602352
    /// </remarks>
    public static IEnumerable<T> RichWhere<T>(this IEnumerable<T> source, RichPredicate<T> predicate)
    {
        return new RichWhereIterator<T>(source, predicate);
    }
    private class RichWhereIterator<T> : IEnumerable<T>, IEnumerator<T>
    {
        private readonly int threadId;
        private readonly IEnumerable<T> source;
        private readonly RichPredicate<T> predicate;
        private IEnumerator<T> enumerator;
        private int state;
        private int countedIndex = -1;
        private int originalIndex = -1;
        private bool hasMoreItems;
        public RichWhereIterator(IEnumerable<T> source, RichPredicate<T> predicate)
        {
            threadId = Thread.CurrentThread.ManagedThreadId;
            this.source = source ?? throw new ArgumentNullException(nameof(source));
            this.predicate = predicate ?? ((item, originalIndex, countedIndex, hasMoreItems) => true);
        }
        public T Current { get; private set; }
        object IEnumerator.Current => Current;
        public void Dispose()
        {
            if (enumerator is IDisposable disposable)
                disposable.Dispose();
            enumerator = null;
            originalIndex = -1;
            countedIndex = -1;
            hasMoreItems = false;
            Current = default(T);
            state = -1;
        }
        public bool MoveNext()
        {
            switch (state)
            {
                case 1:
                    enumerator = source.GetEnumerator();
                    if (!(hasMoreItems = enumerator.MoveNext()))
                    {
                        Dispose();
                        break;
                    }
                    ++originalIndex;
                    state = 2;
                    goto case 2;
                case 2:
                    if (!hasMoreItems) //last predicate returned true and that was the last item
                    {
                        Dispose();
                        break;
                    }
                    T current = enumerator.Current;
                    hasMoreItems = enumerator.MoveNext();
                    ++originalIndex;
                    if (predicate(current, originalIndex - 1, countedIndex + 1, hasMoreItems))
                    {
                        ++countedIndex;
                        Current = current;
                        return true;
                    }
                    else if (hasMoreItems)
                    { goto case 2; }
                    //predicate returned false and there're no more items
                    Dispose();
                    break;
            }
            return false;
        }
        public void Reset()
        {
            Current = default(T);
            hasMoreItems = false;
            originalIndex = -1;
            countedIndex = -1;
            state = 1;
        }
        public IEnumerator<T> GetEnumerator()
        {
            if (threadId == Thread.CurrentThread.ManagedThreadId && state == 0)
            {
                state = 1;
                return this;
            }
            return new RichWhereIterator<T>(source, predicate) { state = 1 };
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}

RichPredicate<T>,可以将其视为Func<T, int, int, bool, bool>提供有关每个项目的信息:

  • 项目:要评估的项目。
  • OriginalIndex :该项目的原始IEnumerable<T>源(直接传递给RichWhere)中的索引。
  • countedIndex :该项目的索引如果谓词将评估为true。
  • HASMOREITEMS :告诉这是否是原始IEnumerable<T>源的最后一项。

相关内容

  • 没有找到相关文章

最新更新