IsOrderedBy Extension Method - c#

In some of my tests i need to check the order of Lists and do it something like this
DateTime lastDate = new DateTime(2009, 10, 1);
foreach (DueAssigmentViewModel assignment in _dueAssigments)
{
if (assignment.DueDate < lastDate)
{
Assert.Fail("Not Correctly Ordered");
}
lastDate = assignment.DueDate;
}
What i would like to do i turn this into an extension method on IEnumerable to make it reusable.
My inital idea was this
public static bool IsOrderedBy<T, TestType>(this IEnumerable<T> value, TestType initalValue)
{
TestType lastValue = initalValue;
foreach (T enumerable in value)
{
if(enumerable < lastValue)
{
return false;
}
lastValue = value;
}
return true;
}
The ovious problem here is you cant compaire to generic values. Can anyone suggest a way round this.
Cheers
Colin

I think it would make more sense to use a method signature similar to the OrderBy method...
public static bool IsOrderedBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
bool isFirstPass = true;
TSource previous = default(TSource);
foreach (TSource item in source)
{
if (!isFirstPass)
{
TKey key = keySelector(item);
TKey previousKey = keySelector(previous);
if (Comparer<TKey>.Default.Compare(previousKey, key) > 0)
return false;
}
isFirstPass = false;
previous = item;
}
return true;
}
You can then use it like that :
List<Foo> list = new List<Foo>();
...
if (list.IsOrderedBy(f => f.Name))
Console.WriteLine("The list is sorted by name");
else
Console.WriteLine("The list is not sorted by name");

You could add a restraint:
where T:IComparable
Then instead of using the < operator, you could use the CompareTo() method of the IComparable interface.

You should do something like this (I can't see why TestType should be different from T):
public static bool IsOrderedBy<T>(this IEnumerable<T> value, T initalValue)
where T : IComparable<T> {
var currentValue = initialValue;
foreach(var i in value) {
if (i.CompareTo(currentValue) < 0)
return false;
currentValue = i;
}
return true;
}

Related

How to apply contain on last record and delete if found in LINQ?

I have a list of strings like
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
Now I want to delete only last record if it does not contains AAPL(symbol name) using LINQ.
Below I have write my code which contains multiple line but I want to make it single line code,
fileLines = System.IO.File.ReadAllLines(fileName).AsParallel().Skip(1).ToList();
var lastLine = fileLines.Last();
if (!lastLine.Contains(item.sym))
{
fileLines.RemoveAt(fileLines.Count - 1);
}
So How can I make all it in single line linq query ?
You could use the ternary operator to decide on the tail to concatenate as follows.
fileLines
= fileLines.Take(fileLines.Count())
.Concat(fileLines.Last().Contains(item.sym) ? Enumerable.Empty
: new string[]{ item.sym });
You could formulate it even more contracted as follows.
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();
That being said, such an endeavour is questionable. The accumulation of lazily evaluated Linq extension methods is difficult to debug.
I understand you need to simplify the filtering operation, and, from what I see in your case, you're missing only one piece of information (i.e whether or not current item is the last one in an enumerated collection) that will help you define your predicate. What I'm about to write now might not seem "a simple single line"; however, it's gonna be a reusable extension that will provide this piece of information (and more) without performing extra and unnecessary loops or iterations.
The final product of that will be:
IEnumerable<string> fileLines = System.IO.File.ReadLines(fileName).RichWhere((item, originalIndex, countedIndex, hasMoreItems) => hasMoreItems || item.StartsWith("AAPL"));
The LINQ-like extension that I wrote inspired by Microsoft's Enumerable at 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>, which could be thought of as Func<T, int, int, bool, bool> provide this information about each item:
item: the item to evaluate.
originalIndex: the index of that item in its original IEnumerable<T> source (the one which was directly passed to RichWhere).
countedIndex: the index of that item IF the predicate would evaluate to true.
hasMoreItems: tells whether or not this would be the last item from the original IEnumerable<T> source.

C# Enumerable.Take with default value

What is the best way to get exactly x values from an Enumerable in C#.
If i use Enumerable .Take() like this:
var myList = Enumerable.Range(0,10);
var result = myList.Take(20);
The result will only have 10 elements.
I want to fill the missing entries with a default value.
Something like this:
var myList = Enumerable.Range(0,10);
var result = myList.TakeOrDefault(20, default(int)); //Is there anything like this?
Is there such a function in C# and if not, what would be the best way to achieve this?
You could do something like:
var result = myList.Concat(Enumerable.Repeat(default(int), 20)).Take(20);
And it would be easy to turn this into an extension method:
public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> list, int count, T defaultValue)
{
return list.Concat(Enumerable.Repeat(defaultValue, count)).Take(count);
}
But there is a subtle gotcha here. This would work perfectly fine for value types, for a reference type, if your defaultValue isn't null, you are adding the same object multiple times. Which probably isn't want you want. For example, if you had this:
var result = myList.TakeOrDefault(20, new Foo());
You are going to add the same instance of Foo to pad your collection. To solve that problem, you'd need something like this:
public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> list, int count, Func<T> defaultFactory)
{
return list.Concat(Enumerable.Range(0, count).Select(i => defaultFactory())).Take(count);
}
Which you'd call like this:
var result = myList.TakeOrDefault(20, () => new Foo())
Of course, both methods can co-exist, so you could easily have:
// pad a list of ints with zeroes
var intResult = myIntList.TakeOrDefault(20, default(int));
// pad a list of objects with null
var objNullResult = myObjList.TakeOrDefault(20, (object)null);
// pad a list of Foo with new (separate) instances of Foo
var objPadNewResult = myFooList.TakeOrDefault(20, () => new Foo());
Its not there by default, but it's easy enough to write as an extension method
public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> items, int count, T defaultValue)
{
var i = 0;
foreach(var item in items)
{
i++;
yield return item;
if(i == count)
yield break;
}
while(i++<count)
{
yield return defaultValue;
}
}
Live example: http://rextester.com/XANF91263
What you're looking for is a general-purpose PadTo method, which extends the collection's length if needed using a given value.
public static IEnumerable<T> PadTo<T>(this IEnumerable<T> source, int len)
{
return source.PadTo(len, default(T));
}
public static IEnumerable<T> PadTo<T>(this IEnumerable<T> source, int len, T elem)
{
return source.PadTo(len, () => elem);
}
public static IEnumerable<T> PadTo<T>(this IEnumerable<T> source, int len, Func<T> elem)
{
int i = 0;
foreach(var t in source)
{
i++;
yield return t;
}
while(i++ < len)
yield return elem();
}
You can now express:
myList.Take(20).PadTo(20);
This is analogous to Scala's List[A].padTo
You could use Concat for this purpose. You can use a simple helper method to join this all together:
public IEnumerable<T> TakeSpawn(this IEnumerable<T> #this, int take, T defaultElement)
{
return #this.Concat(Enumerable.Repeat(defaultElement, take)).Take(take);
}
The idea is that you always append another enumerable on the end of the original enumerable, so if the input doesn't have enough elements, it will start enumerating from the Repeat.
There isn't anything in the .NET Framework, not that I'm aware of. This can be achieved easily using an extension method though and it works for all types if you supply a default value yourself:
public static class ListExtensions
{
public static IEnumerable<T> TakeOrDefault<T>(this List<T> list, int count, T defaultValue)
{
int missingItems = count - list.Count;
List<T> extra = new List<T>(missingItems);
for (int i = 0; i < missingItems; i++)
extra.Add(defaultValue);
return list.Take(count).Concat(extra);
}
}
I wrote a quick extension for this which depends on T being a value type.
public static class Extensions
{
public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> list, int totalElements)
{
List<T> finalList = list.ToList();
if (list.Count() < totalElements)
{
for (int i = list.Count(); i < totalElements; i++)
{
finalList.Add(Activator.CreateInstance<T>());
}
}
return finalList;
}
}
Why not just write an extension method that checks the count and returns the default value for remaining entries:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
List<int> values = new List<int>{1, 2, 3, 4};
IEnumerable<int> moreValues = values.TakeOrDefault(3, 100);
Console.WriteLine(moreValues.Count());
moreValues = values.TakeOrDefault(4, 100);
Console.WriteLine(moreValues.Count());
moreValues = values.TakeOrDefault(10, 100);
Console.WriteLine(moreValues.Count());
}
}
public static class ExtensionMethods
{
public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> enumerable, int count, T defaultValue)
{
int returnedCount = 0;
foreach (T variable in enumerable)
{
returnedCount++;
yield return variable;
if (returnedCount == count)
{
yield break;
}
}
if (returnedCount < count)
{
for (int i = returnedCount; i < count; i++)
{
yield return defaultValue;
}
}
}
}
}

How to return distinct elements from my C# collection?

I have a MongoDB database where I store all pictures and when I retrieve them I have stored some doubles, which ain't so good, but anyway I want to show only distinct elements.
#foreach (Foto f in fotos.Distinct(new IEqualityComparer<Foto> { )
But the Foto class has one property called smallurl and I want to show only distinct elements by this property. So how to write a custom IEqualityComparer.
var listOfUrls = fotos.Select(f => f.smallurl).Distinct();
EDIT to specifically answer your question
Practically copied from the MSDN documentation that you can find with a search for c# IEqualityComparer http://msdn.microsoft.com/en-us/library/ms132151.aspx
class FotoEqualityComparer : IEqualityComparer<Foto>
{
public bool Equals(Foto f1, Foto f2)
{
return f1.smallurl == f2.smallurl;
}
public int GetHashCode(Foto f)
{
return f.smallurl.GetHashCode();
}
}
#foreach (Foto f in fotos.Distinct(new FotoEqualityComparer() )
It's actually pretty easy. Simply provide a distinct-ness selector for your method like so:
public static IEnumerable<TSource> DistinctBy<TSource, TResult>(this IEnumerable<TSource> enumerable, Func<TSource, TResult> keySelector)
{
Dictionary<TResult, TSource> seenItems = new Dictionary<TResult, TSource>();
foreach (var item in enumerable)
{
var key = keySelector(item);
if (!seenItems.ContainsKey(key))
{
seenItems.Add(key, item);
yield return item;
}
}
}
Alternatively, you can create another one to make a generic implementation fo the IEquality comparer:
public static IEnumerable<TSource> DistinctBy<TSource>(this IEnumerable<TSource> enumerable, Func<TSource, TSource, bool> equalitySelector, Func<TSource, int> hashCodeSelector)
{
return enumerable.Distinct(new GenericEqualitySelector<TSource>(equalitySelector, hashCodeSelector));
}
class GenericEqualitySelector<TSource> : IEqualityComparer<TSource>
{
public Func<TSource, TSource, bool> _equalityComparer = null;
public Func<TSource, int> _hashSelector = null;
public GenericEqualitySelector(Func<TSource, TSource, bool> selector, Func<TSource, int> hashSelector)
{
_equalityComparer = selector;
_hashSelector = hashSelector;
}
public bool Equals(TSource x, TSource y)
{
return _equalityComparer(x, y);
}
public int GetHashCode(TSource obj)
{
return _hashSelector(obj);
}
}
Create your own:
public class FotoEqualityComparer : IEqualityComparer<Foto>
{
public bool Equals(Foto x, Foto y)
{
return x.smallurl.Equals(y.smallurl);
}
public int GetHashCode(Foto foto)
{
return foto.smallurl.GetHashCode();
}
}
And use it like so:
fotos.Distinct(new FotoEqualityComparer());
EDIT:
There's no inline lambda overload of .Distinct() because when two objects compare equal they must have the same GetHashCode return value (or else the hash table used internally by Distinct will not function correctly).
But if you want it in one line, then you could also do grouping to achieve the same result:
fotos.GroupBy(f => f.smallurl).Select(g => g.First());
Modified from MSDN
public class MyEqualityComparer : IEqualityComparer<Foto>
{
public bool Equals(Foto x, Foto y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the foto's properties are equal.
return x.smallurl == y.smallurl ;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Foto foto)
{
//Check whether the object is null
if (Object.ReferenceEquals(foto, null)) return 0;
//Get hash code for the foto.smallurl field if it is not null.
return foto.smallurl == null ? 0 : foto.smallurl.GetHashCode();
}
}
Much simpler code using GroupBy instead:
#foreach (Foto f in fotos.GroupBy(f => f.smallurl).Select(g => g.First()))
You should create your own EqulityComparer:
class FotoEqualityComparer : IEqualityComparer<Foto>
{
public bool Equals(Foto b1, Foto b2)
{
if (b1.smallurl == b2.smallurl)
return true;
else
return false;
}
public int GetHashCode(Foto bx)
{
int hCode = bx.smallurl ;
return hCode.GetHashCode();
}
}

Express C# generic type arguments more succinctly?

Inspired by
Comparing two collections for equality irrespective of the order of items in them
I created an extension method to test whether two collections are equivalent. To use the extension method, I have to specify two type parameters like this:
IsEquivalentToTestHelper<ObservableCollection<string>, string>(first, second, true);
Is there a way to implement the extension method so that only one generic constraint (e.g. ObservableCollection<string>) need be specified?
UPDATE: Posted the modified code based on answers as an additional response to the question that inspired this one.
Here's my original code:
static public class EnumerableExtensions
{
static public bool IsEquivalentTo<E,T>(this E first, E second) where E : IEnumerable<T>
{
if ((first == null) != (second == null))
return false;
if (!object.ReferenceEquals(first, second) && (first != null))
{
if (first.Count() != second.Count())
return false;
if ((first.Count() != 0) && HaveMismatchedElement<E,T>(first, second))
return false;
}
return true;
}
private static bool HaveMismatchedElement<E,T>(E first, E second) where E : IEnumerable<T>
{
int firstCount;
int secondCount;
var firstElementCounts = GetElementCounts<E,T>(first, out firstCount);
var secondElementCounts = GetElementCounts<E,T>(second, out secondCount);
if (firstCount != secondCount)
return true;
foreach (var kvp in firstElementCounts)
{
firstCount = kvp.Value;
secondElementCounts.TryGetValue(kvp.Key, out secondCount);
if (firstCount != secondCount)
return true;
}
return false;
}
private static Dictionary<T, int> GetElementCounts<E,T>(E enumerable, out int nullCount) where E : IEnumerable<T>
{
var dictionary = new Dictionary<T, int>();
nullCount = 0;
foreach (T element in enumerable)
{
if (element == null)
{
nullCount++;
}
else
{
int num;
dictionary.TryGetValue(element, out num);
num++;
dictionary[element] = num;
}
}
return dictionary;
}
static private int GetHashCode<E,T>(IEnumerable<T> enumerable) where E : IEnumerable<T>
{
int hash = 17;
foreach (T val in enumerable.OrderBy(x => x))
hash = hash * 23 + val.GetHashCode();
return hash;
}
}
static public bool IsEquivalentTo<T>(this IEnumerable<T> first, IEnumerable<T> second)
You could drop the first one and keep the second:
static public bool IsEquivalentTo<T>(this IEnumerable<T> first, IEnumerable<T> second)
You just need to replace every E with IEnumerable<T>, and drop the where statements
For example:
static public bool IsEquivalentTo<T>(this IEnumerable<T> first, IEnumerable<T> second)
var firstElementCounts = GetElementCounts<IEnumerable<T>,T>(first, out firstCount);
static private int GetHashCode<T>(IEnumerable<T> enumerable)

Minimum of a struct-Array in C#

I used a Select() to perform a calculation on each member of an array of structs and now want to have the member for which a certain attribute is minimal. I wanted to use something like Min() on the selected sequence, but I don't know how to return the full struct, rather than only the attribute that is minmal.
How about ordering by your "value" and taking the first entry (the minimum value):
Persons.OrderBy(p => p.Age).FirstOrDefault();
That is of course if you only want one item (which is what you state).
Alternatively:
from p in Persons
where p.Age == Persons.Select(p1 => p1.Age).Min()
select p;
Will get you all items with minimum value.
Sounds like you want to use MinBy from MoreLINQ:
public static TSource MinBy<TSource, TKey>(this IEnumerable<TSource> source,
Func<TSource, TKey> selector, IComparer<TKey> comparer)
{
source.ThrowIfNull("source");
selector.ThrowIfNull("selector");
comparer.ThrowIfNull("comparer");
using (IEnumerator<TSource> sourceIterator = source.GetEnumerator())
{
if (!sourceIterator.MoveNext())
{
throw new InvalidOperationException("Sequence was empty");
}
TSource min = sourceIterator.Current;
TKey minKey = selector(min);
while (sourceIterator.MoveNext())
{
TSource candidate = sourceIterator.Current;
TKey candidateProjected = selector(candidate);
if (comparer.Compare(candidateProjected, minKey) < 0)
{
min = candidate;
minKey = candidateProjected;
}
}
return min;
}
}
ThrowIfNull is defined as an extension method:
internal static void ThrowIfNull<T>(this T argument, string name)
where T : class
{
if (argument == null)
{
throw new ArgumentNullException(name);
}
}
If i understand correctly, i'd say: use delegates...
Here's an Example from Craig Murphy
public class Person
{
public int age;
public string name;
public Person(int age, string name)
{
this.age = age;
this.name = name;
}
}
// everyone under 25:
List<person> young = people.FindAll(delegate(Person p) { return p.age < 25; });
// sort your list:
people.Sort(delegate(Person p1, Person p2)
{ return p1.age.CompareTo(p2.age); });

Categories

Resources