Can I use LINQ to get only "on change" values?

What I would like to do is build a LINQ query that gets multiple values ​​from some DataRows when changing one of the fields. Here's a contrived example to illustrate:

Observation   Temp  Time
------------- ----  ------
Cloudy        15.0  3:00PM
Cloudy        16.5  4:00PM
Sunny         19.0  3:30PM
Sunny         19.5  3:15PM
Sunny         18.5  3:30PM
Partly Cloudy 16.5  3:20PM
Partly Cloudy 16.0  3:25PM
Cloudy        16.0  4:00PM
Sunny         17.5  3:45PM

I would like to receive only records when the Observation has changed from the previous one. Thus, the results will include:

Cloudy        15.0  3:00PM
Sunny         19.0  3:30PM
Partly Cloudy 16.5  3:20PM
Cloudy        16.0  4:00PM
Sunny         17.5  3:45PM

There is currently code that iterates through DataRows and does comparisons and plotting results, but hoped to use LINQ to do this.

What I would like to do is something like this:

var weatherStuff = from row in ds.Tables[0].AsEnumerable()
                   where row.Field<string>("Observation") != weatherStuff.ElementAt(weatherStuff.Count() - 1) )
                   select row;

But this will not work - and does not compile, since it is trying to use the "weatherStuff" variable before it is declared.

, LINQ? , , .

+1
5

IEnumerable, .

var all = ds.Tables[0].AsEnumerable();
var weatherStuff = all.Where( (w,i) => i == 0 || w.Field<string>("Observation") != all.ElementAt(i-1).Field<string>("Observation") );
+4

, . , , @tvanfosson , , , :-). , , - , . .

LINQ group by, , group by. ( LINQ!). (, GroupByMoving), , IEnumerable , GroupBy . :

var weatherStuff = 
  from row in ds.Tables[0].AsEnumerable().AsMoving()
  group row by row.Field<string>("Observation") into g
  select g.First();

AsMoving GroupBy. , , , , , , , :-). , LINQ , , .

, :

// Interface & simple implementation so that we can change GroupBy
interface IMoving<T> : IEnumerable<T> { }
class WrappedMoving<T> : IMoving<T> {
  public IEnumerable<T> Wrapped { get; set; }
  public IEnumerator<T> GetEnumerator() { 
    return Wrapped.GetEnumerator(); 
  }
  public IEnumerator<T> GetEnumerator() { 
    return ((IEnumerable)Wrapped).GetEnumerator(); 
  }
}

// Important bits:
static class MovingExtensions { 
  public static IMoving<T> AsMoving<T>(this IEnumerable<T> e) {
    return new WrappedMoving<T> { Wrapped = e };
  }

  // This is (an ugly & imperative) implementation of the 
  // group by as described earlier (you can probably implement it
  // more nicely using other LINQ methods)
  public static IEnumerable<IEnumerable<T>> GroupBy<T, K>(this IEnumerable<T> source, 
       Func<T, K> keySelector) {
    List<T> elementsSoFar = new List<T>();
    IEnumerator<T> en = source.GetEnumerator();
    if (en.MoveNext()) {
      K lastKey = keySelector(en.Current);
      do { 
        K newKey = keySelector(en.Current);
        if (newKey != lastKey) { 
          yield return elementsSoFar;
          elementsSoFar = new List<T>();
        }
        elementsSoFar.Add(en.Current);
      } while (en.MoveNext());
      yield return elementsSoFar;
    }
  }
+7

, , , , . , , Linq , - , , .

SQL Server ( ) (ROW_NUMBER), , , Linq, .


, :

public static IEnumerable<T> Changed(this IEnumerable<T> items,
    Func<T, T, bool> equalityFunc)
{
    if (equalityFunc == null)
    {
        throw new ArgumentNullException("equalityFunc");
    }
    T last = default(T);
    bool first = true;
    foreach (T current in items)
    {
        if (first || !equalityFunc(current, last))
        {
            yield return current;
        }
        last = current;
        first = false;
    }
}

:

var changed = rows.Changed((r1, r2) =>
    r1.Field<string>("Observation") == r2.Field<string>("Observation"));
+1

, , , " advar". , , , . , ( -1).

0

Morelinq GroupAdjacent()

GroupAdjacent: ... 4 .

, IGrouping: -

var weatherStuff = ds.Tables[0].AsEnumerable().GroupAdjacent(w => w.Field<string>("Observation"), (_, val) => val.Select(v => v));

This is a very popular extension for standard Linq methods with more than 1M downloads on Nuget (compared to MS Ix.net with ~ 40k download at the time of writing)

0
source

All Articles