Linq Distinct in adjacent rows only

I have a datatable with the following information:

365.00 370.00 369.59 365.00 365.00 -> match with previous item 365.00 -> match with previous item 

I only need to remove the following consistent elements, for example:

 365.00 370.00 369.59 365.00 

I tried:

 (from articlespricehistory in dt.AsEnumerable() select new { articlepricehistory_cost = articlespricehistory.Field<Double>("articlepricehistory_cost") }) .DistinctBy(i => i.articlepricehistory_cost) .ToList(); 

Result:

 365.00 370.00 369.59 

Any ideas?

+6
source share
6 answers

Another approach:

 public static IEnumerable<T> MyDistinct<T>(this IEnumerable<T> items) { T previous = default(T); bool first = true; foreach(T item in items) { if (first || !Equals(previous, item)) { first = false; previous = item; yield return item; } } } 

Or, as requested, with a selector

 public static IEnumerable<T> MyDistinct<T, U>(this IEnumerable<T> items, Func<T, U> selector) { U previous = default(U); bool first = true; foreach(T item in items) { U current = selector(item); if (first || !Equals(previous, current)) { first = false; previous = current; yield return item; } } } 
+7
source

Here's a neat LINQ solution for u

 var list = (dt as Enumerable); var numbers = list.TakeWhile((currentItem, index) => currentItem != list.ElementAtOrDefault(index - 1)); 

Keep in mind that if u has 0 as the first element, it will be excluded from the new list, since ElementAtOrDefault will return 0 in the first iteration of the while loop (index -1), thus evaluating the expression to false. A simple if statement helps you avoid this.

+3
source

Here is an idea that I have not really tried

  • Make a Skip(1) request to request a second request.
  • Now add a second query to any element not equal to the last element in the first query to create a third query.
  • Now zip combines the first and third queries together to form a set of pairs; This is the fourth request.
  • Now create a fifth query that filters out pairs that have identical elements from the fourth query.
  • Finally, we construct the sixth query, which selects the first element of each pair from the fifth query.

The sixth query is the dataset you want.

+2
source

The problem with your query is that you are using .DistinctBy() , which will only return individual results. Therefore, if 365.00 appeared anywhere, it will not appear in the returned list again.

 var differentPreviousList = new List<double>(); var itemPriceList = dt.ToList(); differentPreviousList.Add(itemPriceList[0]); for (var index = 1; index < itemPriceList.Count; index++) { if (itemPriceList[index - 1] == itemPriceList[index]) continue; differentPriceList.Add(itemPriceList[index]); } 
+1
source

I think you need to use a temporary value to check if the next value matches the current value or not.

 double temporary = -1; // temp value for checking List<double> results = new List<double>(); // list to store results (from articlespricehistory in dt.AsEnumerable() select new { articlepricehistory_cost = articlespricehistory.Field<Double>("articlepricehistory_cost") }) .Select(a => a.articlepricehistory_cost) .ToList() .ForEach(cost => { if (temporary != cost) { results.Add(cost); } temporary = cost; }); foreach (var result in results) { Console.WriteLine(result); } 

After ForEach method is equivalent to the following.

 foreach (var cost in costs) { if (temporary != cost) { results.Add(cost); Console.WriteLine(cost); } temporary = cost; } 
0
source

It may not be an elegant solution, but I would just parse a bare request ... here's how.

  • Run the lambda query to get all the original results without trying to filter out DistinctBy.
  • Create an object from one query result for the type you originally requested.
  • Initialize a new list for foreach parsing results.
  • Do for each cycle for each result.
  • First, if the section should be if (the object above the loop is null).
  • IF is the true item to add to the list.
  • ELSE, if you want to check if the value of an element matches the last iteration.
  • Save foreach iteration to an object declared before the loop.

Rinse and repeat, and the result will not duplicate the objects found in the loop line, will be saved in the list, resulting in what you want.

0
source

All Articles