/// <summary> /// Groups element into sub-lists of adjacent that share the same property, true or false, from the predicate. /// Basically performs edge detection in order to operate. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="elements"></param> /// <param name="predicate"></param> /// <returns></returns> public static IEnumerable <Tuple <IEnumerable <T>, bool> > ClusteredByPredicate <T>(this IEnumerable <T> elements, Func <T, bool> predicate) { // We'll build a list assigning numeric, so we can have true, false AND "added at the front" for edge detection purposes. var withTrueFalseAsOneZero = Alg.ReadPoint(elements.Select(x => Tuple.Create(x, predicate(x) ? 1 : 0))).TakenToEnd(); return(Alg.Map( (c, prior) => { var cf = c.First(); return Alg.When( cf.Item2 != prior.Item2, () => Tuple.Create(c.TakeWhile(x => x.Item2 == cf.Item2).Select(x => x.Item1), (cf.Item2 == 1))); }, withTrueFalseAsOneZero.Tails().Where(x => x.Any()), new[] { Tuple.Create(default(T), -1) }.Concat(withTrueFalseAsOneZero)).SelectMany(x => x.ToEnumerable())); }
public static IEnumerable <IEnumerable <T> > Transpose <T>(this IEnumerable <IEnumerable <T> > original) { var orp = Alg.ReadPoint(original); if (!orp.AtEnd) { int numHorizontalInOriginal = orp.Value.Count(); // We cache this var originalsAsArrays = Alg.ReadPoint(original.Select(row => { var r = row.ToArray(); if (r.Length != numHorizontalInOriginal) { throw new Exception("Row size mismatch"); } return(r); })).TakenToEnd(); return(Enumerable.Range(0, numHorizontalInOriginal).Select(ordinal => originalsAsArrays.Select(row => row[ordinal]))); } return(new IEnumerable <T>[] { }); }
public static IEnumerable <string> CharsToLines(IEnumerable <char> chars) { List <char> accumulator = new List <char>(); ReadPoint <char> currentChar = Alg.ReadPoint(chars); while (!currentChar.AtEnd) { char c = currentChar.Value; if (c == '\n') { yield return(Alg.MergedChars(accumulator)); accumulator = new List <char>(); } else if (c == '\r') { // have to handle '\r'-only case. if (!currentChar.Next.AtEnd) { if (currentChar.Next.Value != '\n') { yield return(Alg.MergedChars(accumulator)); accumulator = new List <char>(); } } } else { accumulator.Add(c); } currentChar = currentChar.Next; } if (accumulator.Count != 0) { yield return(Alg.MergedChars(accumulator)); accumulator = new List <char>(); } }
public static IEnumerable <string> LineToCSFEntries(string line, char delimiter, bool quotesHaveMeaning) { ReadPoint <char> currentChar = Alg.ReadPoint(line.ToCharArray()); List <char> accumulatedElement = new List <char>(); bool inQuote = false; bool haveSeenAComma = false; while (!currentChar.AtEnd) { char c = currentChar.Value; if (inQuote) { if (c == '\"') { // may be a double-quote if (IsAtCSVQuote(currentChar)) { accumulatedElement.Add('\"'); currentChar = currentChar.Next; // next add will be done at end of this loop. } else { accumulatedElement.Add(c); inQuote = false; } } else { accumulatedElement.Add(c); } } else { if (c == delimiter) { haveSeenAComma = true; yield return(Alg.MergedChars(accumulatedElement).Trim()); accumulatedElement = new List <char>(); } else { if (quotesHaveMeaning && (c == '\"')) { inQuote = true; accumulatedElement.Add(c); } else { accumulatedElement.Add(c); } } } currentChar = currentChar.Next; } if ((accumulatedElement.Count != 0) || haveSeenAComma) { yield return(Alg.MergedChars(accumulatedElement).Trim()); // deliberately return "last" accumulatedElement = new List <char>(); } }
public static IEnumerableReenumerable <T> Memoized <T>(this IEnumerable <T> source) { return(Alg.ReadPoint(source).TakenToEnd()); }
public static IEnumerableReenumerable <T> ShuffledWithWeights <T>(this IEnumerable <T> source, Func <T, int> weightAccess, Func <int, int> random) { return(Alg.ReadPoint(ShuffledAssist(source, weightAccess, random)).TakenToEnd()); }
// Memoizes/caches its result, subsequent scans of the same result will give the same sequence. public static IEnumerableReenumerable <T> Shuffled <T>(this IEnumerable <T> source, Func <int, int> random) { // standard shuffle: everything has a weight of 1 return(Alg.ReadPoint(ShuffledAssist(source, item => 1, random)).TakenToEnd()); }
public static IEnumerable <IEnumerable <T> > Tails <T>(this IEnumerable <T> original) { return(Alg.ReadPoint(original).AllReadPointsDownIncludingEnd().Select(x => x.TakenToEnd())); }