Actual difference between two lists - not Except - c#

Let's say I have the list
var L1 = new List<int>{1,1,2};
var L2 = new List<int>{1};
If I do
L1.Except(L2)
I get List<int>{2} - Fair enough.
But is there shorthand to do something like L1.Minus(L2) where I would get List<int>{1,2}
Basically only remove items as many times as it finds them in L2.
I could write this out - hoping I don't have to.

If you were to write it yourself, it could look like this:
public static class ExtensionMethods
{
static public IEnumerable<T> Minus<T>(this IEnumerable<T> input, IEnumerable<T> removal)
{
var result = input.ToList();
foreach (var r in removal) result.Remove(r);
return result;
}
}
Or possibly like this if you aren't so worried about readability:
public static class ExtensionMethods
{
static public IEnumerable<T> Minus<T>(this IEnumerable<T> input, IEnumerable<T> removal)
{
var remaining = removal.ToList();
return input.Where
(
a => !remaining.Remove(a)
);
}
}
Example usage:
public class Program
{
public static void Main()
{
var L1 = new List<int>{1,1,2};
var L2 = new List<int>{1};
var L3 = L1.Minus(L2);
foreach (var l in L3)
{
Console.WriteLine(l);
}
}
}
Output:
1
2
Working example on DotNetFiddle

Minimal example using ForEach and a lambda expression:
L2.ForEach(x => L1.Remove(x));

Related

Implement class to work with real time data

Using C# I need to transform a time series, for example:
Input: 1 2 1 0 3 2 -> Output: 1 3 4 4 7 9
In the previous example an output is the sum of current input with the previous inputs.
I will have different transformations so I started with an abstract class:
public abstract class Transformation<TInput, TOutput> {
private IEnumerable<TInput> _inputs { get; set; }
public Transformation(IEnumerable<TInput> inputs) {
_inputs = inputs;
}
public abstract IEnumerable<TOutput> Calculate();
}
So a transformation would be something like:
public class TransformationOne<Int32, Int32> {
public override IEnumerable<Int32> Calculate();
// Calculate the outputs with all inputs
}
}
This works fine if I have all inputs and want all outputs.
But sometimes I would like to use my class in real time.
So I would feed with a new input and would get a new output.
What would be the best way to implement this?
Keep the state in the class and send the input to the Calculate method?
class TransformationOne
{
private int _currentResult;
public int Calculate(int value)
{
_currentResult += value;
return _currentResult;
}
}
so you could do:
var transformationOne = new TransformationOne();
var inputs = new List<int> {1, 2, 1, 0, 3, 2};
foreach (var input in inputs)
{
var newResult = transformationOne.Calculate(input);
Console.WriteLine(newResult); // results: 1 3 4 4 7 9
}
Demo
My answer is very similar to what #Julian did. However, I had already written my solution, I think it does a better job of providing the two aspects of the OP's question:
How to do this for a sequence of data (like what was originally shown)
How do use the same capability for one-at-a-time data
You can't easily do this with a generic, there is no way to constrain a type to one that includes addition (if you know of one, let me now). So this is what the transformation class looks like:
public class AccumulateTransformer
{
private int currentState = 0;
public void Clear()
{
currentState = default(int);
}
public int NextValue(int input)
{
currentState += input;
return currentState;
}
public int Current => currentState;
public IEnumerable<int> TransformSequence(IEnumerable<int> inputs, bool clearFirst = true)
{
if (clearFirst)
{
Clear();
}
foreach (var value in inputs)
{
yield return NextValue(value);
}
}
}
And here's some code to test it (using your data):
var transformer = new AccumulateTransformer();
var inputs = new[] {1, 2, 1, 0, 3, 2,};
var results = transformer.TransformSequence(inputs);
Debug.WriteLine(string.Join(", ", from result in results select result.ToString() ));
transformer.Clear();
Debug.WriteLine(transformer.NextValue(1));
Debug.WriteLine(transformer.NextValue(2));
Debug.WriteLine(transformer.NextValue(1));
Debug.WriteLine(transformer.NextValue(0));
Debug.WriteLine(transformer.NextValue(3));
Debug.WriteLine(transformer.NextValue(2));
The output of that looks like:
1, 3, 4, 4, 7, 9
1
3
4
4
7
9
To make this generic, you need a way of doing the accumulation operation that isn't dependent on T understanding addition. To do that, change the code to what's show below.
It makes the type generic on T (which would be int in this case), but includes a constructor that takes a Func<T, T, T> that will do the accumulation. When you construct your instance, you provide a Func that just adds two numbers.
The class code:
public class AccumulateTransformer<T>
{
private T _currentState = default(T);
private Func<T, T, T> _accumulator;
public AccumulateTransformer(Func<T, T, T> accumulator)
{
_accumulator = accumulator;
}
public void Clear()
{
_currentState = default(T);
}
public T NextValue(T input)
{
_currentState = _accumulator(_currentState, input);
return _currentState;
}
public T Current => _currentState;
public IEnumerable<T> TransformSequence(IEnumerable<T> inputs, bool clearFirst = true)
{
if (clearFirst)
{
Clear();
}
foreach (var value in inputs)
{
yield return NextValue(value);
}
}
The only difference in using this is that you have to provide that accumulate Func in the constructor:
var transformer = new AccumulateTransformer<int>((a, b) => a + b);
Otherwise, it's used the same way and produces the same output.
I'm not sure if this is exactly what you're after, but you could simply keep a list of the items in the class, and provide public methods for adding new items to it:
public class Transformer
{
private readonly List<int> items = new List<int>();
public IEnumerable<int> Items => items.ToList();
public void Add(int item) => items.Add(items.LastOrDefault() + item);
public void Add(IEnumerable<int> input)
{
foreach (var item in input) Add(item);
}
public override string ToString()
{
return string.Join(", ", Items);
}
}
In use it might look like:
public static void Main(string[] args)
{
var trans = new Transformer();
var items = new[] { 1, 2, 1, 0, 3 };
// Add a bunch of inputs at once:
trans.Add(items);
// Display results
Console.WriteLine($"After adding 5 items: {trans}");
// Add a single item
trans.Add(2);
// Display results
Console.WriteLine($"After adding 1 more item: {trans}");
GetKeyFromUser("\nDone! Press any key to exit...");
}
Output
A simple Linq.Select() would do that:
int sum = 0;
var result = input.Select(x => { sum += x; return sum; });
Live Demo

Custom extension methods on IEnumerable<T>

In my project we are getting different list and array of elements and need to pick alternative for those list and array for example if my list consist of
string[] toys= { "car", "bat-mask", "halloween-toys", "marvel-toys", "transformer" };
now it may be a list of hundreds of elements my problems is to choose alternative from above list like if i have configuratioin to pick one after another i.e car after that skip bat-mask and pick halloween-toys this is my first priority and after that i make it configurable like how many item to skip in between like one item or two items etc.
Reason to use it as extension because it will be use inside complete app and i simply need it access like var myList = toys.customExtensionMethods();
You can use that:
using System.Linq;
static public class IEnumerableHelper
{
static public IEnumerable<T> customExtensionMethods<T>(this IEnumerable<T> items,
T takeFirst,
int skipCount)
{
var list1 = items.SkipWhile(item => !item.Equals(takeFirst));
var list2 = list1.Skip(skipCount + 1).Take(1);
return list1.Take(1).Concat(list2);
}
}
Test 1
static void Test()
{
string[] toys = { "car", "bat-mask", "halloween-toys", "marvel-toys", "transformer" };
var list = toys.customExtensionMethods("car", 1);
foreach ( var item in list )
Console.WriteLine(item);
}
Output:
car
halloween-toys
Test 2
var list = toys.customExtensionMethods("bat-mask", 2);
Output
bat-mask
transformer
If i am not wrong, inside your extension method you want to get array element with no Of skip value passed.
public static class ExtensionMethod
{
public static string[] CustomExtensionMethods(this string[] myData, int NoofSkip)
{
var newData = new List<string>();
for (int i = 0; i < myData.Length; i++ )
{
newData.Add(myData[i]);
i = i + NoofSkip;
}
return newData.ToArray();
}
}
Call Method:
var data = toys.CustomExtensionMethods(1);
OutPut:
{ "car", "halloween-toys", "transformer" };
I hope I understood your question correctly. You are intending to create an extension method which takes an input 'searchterm' and a count skip count. The method searches for the item in the list, skips the next n items and returns the new item. You could do as the following.
public static class Extensions
{
public static T PickAlternative<T>(this IEnumerable<T> source,string item,int skipCount)
{
return source.SkipWhile(x=> !x.Equals(item)).Skip(skipCount).First();
}
}
Example,
toys.PickAlternative("bat-mask",3);
toys.PickAlternative("car",2);
Output
transformer
halloween-toys
public static class EnumerableExtensions
{
public static IEnumerable<T> PickAlternate<T>(this IEnumerable<T> source, int skip)
{
int? currentlySkipped = null;
foreach (var item in source)
{
if (!currentlySkipped.HasValue || currentlySkipped == skip)
{
currentlySkipped = 0;
yield return item;
}
else
{
currentlySkipped++;
}
}
}
}

Assert two different types of enumerations are equivalent

I have an NUnit unit test which I have two collections of different types which I want to assert are equivalent.
class A { public int x; }
class B { public string y; }
[Test]
public void MyUnitTest()
{
var a = GetABunchOfAs(); // returns IEnumerable<A>
var b = GetABunchOfBs(); // returns IEnumerable<B>
Assert.IsPrettySimilar(a, b, (argA, argB) => argA.ToString() == argB);
}
where Assert.IsPrettySimilar is defined like such
public static void IsPrettySimilar<T1, T2>(
IEnumerable<T1> left,
IEnumerable<T2> right,
Func<T1, T2, bool> predicate)
{
using (var leftEnumerator = left.GetEnumerator())
using (var rightEnumerator = right.GetEnumerator())
{
while (true)
{
var leftMoved = leftEnumerator.MoveNext();
if (leftMoved != rightEnumerator.MoveNext())
{
Assert.Fail("Enumerators not of equal size");
}
if (!leftMoved)
{
break;
}
var isMatch = predicate(leftEnumerator.Current,
rightEnumerator.Current);
Assert.IsTrue(isMatch);
}
}
}
My question is, is there a more idiomatic way of doing the above with the existing methods in NUnit? I already looked at CollectionAssert and there's nothing matching what I want to do.
My description of "equivalent" in this case is:
1) Collections must be of same size
2) Collections must be in same logical order
3) Some predicate must be used to determine equivalence between matching items.
Let's think what you are trying to test. You are not trying to test that objects from first sequence are same as objects from second sequence. They can be very different. So, word similar is very vague here. What you really trying to test here, is that some projection of first sequence is equal to other projection of second sequence. And NUnit already have such functionality:
CollectionAssert.AreEqual(bunchOfAs.Select(a => a.ToString()),
bunchOfBs.Select(b => b));
Thus you are projecting both sequences to get particular data, then you can give nice names for these two projections, which will make your test readable to others. You have some hidden business logic here, which does not have explanation in code - you don't explain why you making such projections. So, nice names of projection results will explain your intent. E.g:
var expectedNames = employees.Select(u => u.Login);
var actualNames = customers.Select(c => c.Name);
CollectionAssert.AreEqual(expectedNames, actualNames);
That is much cleaner for me than
Assert.IsPrettySimilar(employees, customers, (e, c) => u.Login == c.Name);
I know you looked into CollectionAssert, however, I have found a strategy like this very useful in my own tests.
Overriding ToString and Equals on the objects makes this test pass.
[TestFixture]
public class Class1
{
[Test]
public void MyUnitTest()
{
var a = GetABunchOfAs(); // returns IEnumerable<A>
var b = GetABunchOfBs(); // returns IEnumerable<B>
CollectionAssert.AreEqual(a, b.OrderBy(x => x.y));
}
public List<A> GetABunchOfAs()
{
return new List<A>
{
new A() {x = 1},
new A() {x = 2},
new A() {x = 3},
new A() {x = 4}
};
}
public List<B> GetABunchOfBs()
{
return new List<B>
{
new B() {y = "4"},
new B() {y = "1"},
new B() {y = "2"},
new B() {y = "3"},
};
}
}
public class A
{
public int x;
public override bool Equals(object obj)
{
return obj.ToString().Equals(x.ToString());
}
public override string ToString()
{
return x.ToString();
}
}
public class B
{
public string y;
public override string ToString()
{
return y;
}
public override bool Equals(object obj)
{
return obj.ToString().Equals(y);
}
}
I deliberately left GetABunchOfBs out of order, however the test still passes.
It looks like Sergey's answer is the one I'm looking for (which was to see whether NUnit already has a facility to do what I want). However, this is the solution I ended up with, which is closer to the implementation I want.
public static class EnumerableAssert
{
public static void AreEquivilent<TExpected, TActual>(IEnumerable<TExpected> expected, IEnumerable<TActual> actual, Func<TExpected, TActual, bool> predicate)
{
if (ReferenceEquals(expected, actual))
{
return;
}
using (var expectedEnumerator = expected.GetEnumerator())
using (var actualEnumerator = actual.GetEnumerator())
{
while (true)
{
var expectedMoved = expectedEnumerator.MoveNext();
if (expectedMoved != actualEnumerator.MoveNext())
{
Assert.Fail("Expected and Actual collections are of different size");
}
if (!expectedMoved)
{
return;
}
Assert.IsTrue(predicate(expectedEnumerator.Current, actualEnumerator.Current));
}
}
}
}

What is the cleanest way to do an outer join without equals?

I have two lists, I need to find the items in the first list that are missing from the second, but I can only compare them with a Boolean function.
class A
{
internal bool Matching(A a)
{
return true;
}
}
class OuterMatch
{
List<A> List1 = new List<A>();
List<A> List2 = new List<A>();
void BasicOuterJoin()
{
// textbook example of an outer join, but it does not use my Matching function
var missingFrom2 = from one in List1
join two in List2
on one equals two into matching
from match in matching.DefaultIfEmpty()
where match == null
select one;
}
void Matching()
{
// simple use of the matching function, but this is an inner join.
var matching = from one in List1
from two in List2
where one.Matching(two)
select one;
}
void MissingBasedOnMatching()
{
// a reasonable substitute for what I'm after
var missingFrom2 = from one in List1
where (from two in List2
where two.Matching(one)
select two)
.Count() == 0
select one;
}
MissingBasedOnMatching gives me the right results, but it's not visually obviously an outer join like BasicOuterJoin is. Is there a clearer way to do this?
There's a form of GroupJoin that takes a comparison operator, but I'm not clear if there is a way to use it to make an outer join.
I've been using some useful (and short!) code from a blog by Ed Khoze.
He's posted a handy class which provides an adapter so that you can use Enumerable.Except() with a lambda.
Once you have that code, you can use Except() to solve your problem like so:
var missing = list1.Except(list2, (a, b) => a.Matching(b));
Here's a complete compilable sample. Credit to Ed Khoze for the LINQHelper class:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
class A
{
public int Value;
public bool Matching(A a)
{
return a.Value == Value;
}
public override string ToString()
{
return Value.ToString();
}
}
class Program
{
void test()
{
var list1 = new List<A>();
var list2 = new List<A>();
for (int i = 0; i < 20; ++i) list1.Add(new A {Value = i});
for (int i = 4; i < 16; ++i) list2.Add(new A {Value = i});
var missing = list1.Except(list2, (a, b) => a.Matching(b));
missing.Print(); // Prints 0 1 2 3 16 17 18 19
}
static void Main()
{
new Program().test();
}
}
static class MyEnumerableExt
{
public static void Print<T>(this IEnumerable<T> sequence)
{
foreach (var item in sequence)
Console.WriteLine(item);
}
}
public static class LINQHelper
{
private class LambdaComparer<T>: IEqualityComparer<T>
{
private readonly Func<T, T, bool> _lambdaComparer;
private readonly Func<T, int> _lambdaHash;
public LambdaComparer(Func<T, T, bool> lambdaComparer) :
this(lambdaComparer, o => 0)
{
}
private LambdaComparer(Func<T, T, bool> lambdaComparer, Func<T, int> lambdaHash)
{
if (lambdaComparer == null)
throw new ArgumentNullException("lambdaComparer");
if (lambdaHash == null)
throw new ArgumentNullException("lambdaHash");
_lambdaComparer = lambdaComparer;
_lambdaHash = lambdaHash;
}
public bool Equals(T x, T y)
{
return _lambdaComparer(x, y);
}
public int GetHashCode(T obj)
{
return _lambdaHash(obj);
}
}
public static IEnumerable<TSource> Except<TSource>
(
this IEnumerable<TSource> enumerable,
IEnumerable<TSource> second,
Func<TSource, TSource, bool> comparer
)
{
return enumerable.Except(second, new LambdaComparer<TSource>(comparer));
}
}
}
If your problem statement is actually
Find all members of X that do not exist in Y
And given a class Foo that implements IEquatable<Foo> (pretty much what your Matching method does):
class Foo : IEquatable<Foo>
{
public bool Equals( Foo other )
{
throw new NotImplementedException();
}
}
Then this code should give you what you want:
List<Foo> x = GetFirstList() ;
List<Foo> y = GetSecondList() ;
List<Foo> xNotInY = x.Where( xItem => ! y.Any( yItem => xItem.Equals(yItem) ) ).ToList() ;
You should bear in mind that this runs in O(N2) time. Consequently, you might want to implement an IEqualityComparer<Foo> and put your second list in a HashSet<Foo>:
class FooComparer : IEqualityComparer<Foo>
{
public bool Equals(Foo x, Foo y)
{
if ( x == null )
{
return y == null ;
}
else if ( y == null ) return false ;
else
{
return x.Equals(y) ;
}
}
public int GetHashCode(Foo obj)
{
return obj.GetHashCode() ;
}
}
Then do something like
List<Foo> x = GetFirstList() ;
List<Foo> y = GetSecondList() ;
HashSet<Foo> yLookup = new HashSet<Foo>( y , new FooComparer() ) ;
List<Foo> xNotInY = x.Where( x => !yLookup.Contains(x) ) ;
You'll incur some overhead in constructing the hash set (1 pass through the second list), but subsequent lookups via Contains() are O(1).
If you look at the sources for the Linq join operation, this is close to what it does.
It wouldn't be difficult to strip the Linq sources for Join() and it's helpers and tweak them to product left and right join operators instead of the stock inner join.
Does this work for your purposes?
var missing = List1.Except(List2);
If you need custom comparison logic you can build a custom IEqualityComparer. Note however that Except treats both lists as sets, so it will eliminate duplicates from List1.

Multiple columns in Linq

Problem: how to simplify the code below, as I'm aiming towards 30 different properties in the thing class.
The code looks for uniqueness in a 'thing' property.
public class thing
{
public string Name { get; set; }
public string Colour { get; set; }
public string Position { get; set; }
public string Height { get; set; }
}
public List<thing> SeeIfAnyInListHaveAUniqueSingleColumn(List<thing> listOfThings)
{
// try colour
IEnumerable<IGrouping<string, thing>> thingQuery2 = from t in listOfThings
group t by t.Colour;
List<thing> listOfThingsFound = new List<thing>();
foreach (var thingGroup in thingQuery2)
{
if (thingGroup.Count() == 1)
{
foreach (thing thing in thingGroup) // there is only going to be 1
listOfThingsFound.Add(thing);
}
}
// try position
IEnumerable<IGrouping<string, thing>> thingQuery3 = from t in listOfThings
group t by t.Position;
foreach (var thingGroup in thingQuery3)
{
if (thingGroup.Count() == 1)
{
foreach (thing thing in thingGroup) // there is only going to be 1
listOfThingsFound.Add(thing);
}
}
return listOfThingsFound;
}
Downloadable code on http://www.programgood.net/2010/11/06/FindingUniquenessInData.aspx
I think that if you abstract away the FindUnique operation, you can more easily write the tests:
static IEnumerable<T> FindDistinct<T, TKey>(this IEnumerable<T> source,
Func<T, TKey> keySelector)
{
return from item in source
group item by keySelector(item) into grp
where grp.Count() == 1
from single in grp
select single;
}
Then you can write:
var thingsWithUniqueName = listOfThings.FindDistinct(t => t.Name);
var thingsWithUniquePosition = listOfThings.FindDistinct(t => t.Position);
var thingsWithUniqueHeight = listOfThings.FindDistinct(t => t.Height);
You would like to write code like:
foreach var property in Thing.Properties
{
IEnumerable<IGrouping<string, thing>> thingQuery2 = from t in listOfThings
group t by t.property;
List<thing> listOfThingsFound = new List<thing>();
foreach (var thingGroup in thingQuery2)
{
if (thingGroup.Count() == 1)
{
foreach (thing thing in thingGroup) // there is only going to be 1
listOfThingsFound.Add(thing);
}
}
...
}
You can only do that through Reflection and that is something you should stay away from. The only thing I can think of is store the properties in some kind of collection, like a dictionary and iterate that.
I just noticed that Gabe has provided the same answer I was about to post. I thought I would post this anyway just to reinforce that this answer is a good strong use of LINQ. Please accept Gabe's answer rather than this one. Well done Gabe!
public static IEnumerable<T> WhereUniqueByKey<T, P>(
this IEnumerable<T> #this, Func<T, P> keySelector)
{
return #this
.GroupBy(keySelector)
.Where(gt => gt.Count() == 1)
.SelectMany(gt => gt, (_, t) => t);
}
As per Gabe's answer, my function is an extension method, and it needs to be defined in a static class. The only real difference between our answers is that Gabe has used the LINQ query syntax and I used direct LINQ method calls. The result is the same and so is the usage:
var thingsWithUniqueName = listOfThings.WhereUniqueByKey(t => t.Name);
var thingsWithUniquePosition = listOfThings.WhereUniqueByKey(t => t.Position);
var thingsWithUniqueHeight = listOfThings.WhereUniqueByKey(t => t.Height);

Categories