This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Except has similar effect to Distinct?
I'm having two List<String> like
lstOne = { "A", "B", "C" ,"C" ,"C" };
lstTwo = { "A" };
lstResult = lstOne.Except(lstTwo).ToList();
Now the expected output is
lstReult = { "B","C","C","C" };
But the actula result is like
lstResult = { "B","C" };
Why its so? i've used Except , why its applying Distinct too?
"Except" is documented as returning the set difference of two sequences.
The set difference by definition is a set. Sets by definition don't have duplicates.
the expected output is ...
No, the expected output is identical to the actual output.
If you expect something different, my advice is to adjust your expectations to match the documented behaviour.
It is documented as returning "A sequence that contains the set difference of the elements of two sequences.". Sets do not have duplicates.
It is perhaps a subtle point, but it functions as per the spec.
If you want the dups:
var lstOne = new[] { "A", "B", "C" ,"C" ,"C" };
var except = new HashSet<string> { "A" };
var lstResult = lstOne.Where(x => !except.Contains(x)).ToList();
// ^^ "B", "C", "C", "C"
MSDN Definition: "Produces the set difference of two sequences by using the default equality comparer to compare values." --> Difference as set --> each key is unique.
Related
This question already has answers here:
Generating all Possible Combinations
(12 answers)
Closed 7 years ago.
Lets say I have three list:
A = {"b", "c", "d", "x", "y", "z"}
B = {"a", "e", "i"}
I want to generate all combinations of selecting one element from both list.
For just 2 list this is easy (pseuodo-ish code):
combinations = []
for a in A:
for b in B:
combinations += [a, b]
But what if the number of lists is unknown? I want to generalize this somehow preferrably with a C# extension method.
The method signature would be something like this:
public static IEnumerable<IEnumerable<T>> Combination<T>(this IEnumerable<IEnumerable<T>> elements)
EDIT:
I was looking for Cartesian product, thanks for clarification.
If you are just flat combining, and you have a set of these sets, you should be able to simply use a SelectMany on the sets.
public static IEnumerable<[T]> Combination<T>(this IEnumerable<IEnumerable<T>> elements)
{
return elements.Select(
e => elements.Except(e).SelectMany( t => new T[e,t] )
);
}
Assuming you want all combinations including the ones with duplicate elements in a different order, this is basically what the existing method SelectMany does.
It's fairly easy to get all combinations using query expressions and anonymous objects. Here's an example:
var combinations = from a in allAs
from b in allBs
select new { A = a, B = b };
Doing this in one fell swoop (using the proposed Combination method) would at least require you to:
Provide a function to "select" a combination (similar to the signature of the Zip method)
Or, return a generic Tuple<T, T>
But then again, it's really just replacing the usage of a cartesian product (SelectMany) and a projection (Select), both of which already exist.
This question already has answers here:
How to Sort a List<T> by a property in the object
(23 answers)
Closed 7 years ago.
I have a list
List<string[]> listname = ...
The list looks like this:
[string][string][string]
I want to sort the list by second string.
The second string is a number presented as a string, i want to keep it that way, i need it like this.
I want the numbers to be in Increasing order.
Example for data:
["RDP"]["3389"]["TCP"]
["HTTP"]["80"]["TCP"]
["HTTPS"]["443"]["TCP"]
I want to sort by the post number.
In this example "RDP" will become the last one.
How can I do so?
var sortedList = listname.OrderBy(l => int.Parse(l[1]));
This assumes that the second entry in each array is parsable as int. If you're not sure about that, you'd need to add some checks and maybe use int.TryParse.
You can refer to appropriate index of an array in OrderBy:
var l = new List<string[]>() {
new string[] { "a", "b", "c" },
new string[] { "b", "a", "c" },
new string[] { "c", "c", "c" },
};
var s = l.OrderBy(c => c[1]).ToList();
This question already has answers here:
Check whether an array is a subset of another
(10 answers)
Closed 8 years ago.
Let's I have 2 arrays string[] A = { "a", "b", "c" } and string[] B = { "a", "b", "c", "d", "e" }.
Is there any method that can tell directly that A is a subset of B? Except will just remove distinct elements of B, but won't tell whether it's completely a subset of B.
Thank you for helping.
you can do this,simply:
A.All(B.Contains);
And you may wanna check the Length to make sure they are not the same size and A is a subset
bool isSubset = A.All(B.Contains) && A.Length < B.Length;
There's even a method for this purpose. You could use HastSet<T>.IsSubsetOf:
var aSet = new HashSet<string>(A);
bool isASubsetOfB = aSet.IsSubsetOf(B);
This should work
bool isSubSet = !A.Except(B).Any();
You can combine SequenceEquals and Intersect:
var isASubsetOfB = B.Intersect(A).SequenceEqual(A)
I have two lists of strings both of which are ~300,000 lines. List 1 has a few lines more than List 2. What I'm trying to do is find the strings that in List 1 but not in List 2.
Considering how many strings I have to compare, is Except() good enough or is there something better (faster)?
Internally the enumerable Except extension method uses Set<T> to perform the computation. It's going to be as least as fast as any other method.
Go with list1.Except(list2).
It'll give you the best performance and the simplest code.
My suggestion:
HashSet<String> hash1 = new HashSet<String>(new string[] { "a", "b", "c", "d" });
HashSet<String> hash2 = new HashSet<String>(new string[] { "a", "b" });
List<String> result = hash1.Except(hash2).ToList();
List<string> a = new List<string>() { "a", "b", "c" };
List<string> b = new List<string>() { "a", "b", "c", "d", "e", "f" };
b.RemoveAll(a.Contains);
If you loop through b it will now only contain d e and f. Can anyone expand out whats actually happening, because currently it doesnt make any sense at all.
Edit: I was more talking about the use of predicates. How does know how to pass what into where?
b.RemoveAll(<function that takes a string and returns true if we want to remove it>)
no lambda expression required.
perhaps you'd like for the line to read
b.RemoveAll(x => a.Contains(x))
however, the function x=> a.Contains(x) is simply a function that takes a string and returns a bool indicating whether a contains x. a.Contains is already a function that does that.
The { } Syntax is a collection initializer. The code is equivalent to
List<string> a = new List<string>();
a.Add("a");
a.Add("b");
a.Add("c");
List<string> b = new List<string>();
b.Add("a");
b.Add("b");
b.Add("c");
b.Add("d");
b.Add("e");
b.Add("f");
b.RemoveAll is a function that calls another function and passes in a string. It's like this:
foreach(string s in b) {
if(FunctionToCall(s) == true) b.Remove(s);
}
a.Contains is a function that takes a string and returns a bool. So the code can be changed to:
foreach(string s in b) {
if(a.Contains(s)) b.Remove(s);
}
Note that in this Lambda-Syntax, you are passing the "a.Contains" function - not the result of the function! It's like a function pointer. RemoveAll expects to take a function in the form of "bool FunctionName(string input)".
Edit: Do you know what delegates are? They are a bit like function pointers: A delegate specifies a signature ("Takes 2 strings, returns an int"), and then you can use it like a variable. If you don't know about delegates, read Karl Seguins article.
Some delegates are needed extremely often, so the .net Framework developers added three types of extremely common delegates:
Predicate: A delegate that takes a T and returns a bool.
Action: A delegate that takes 1 to 4 parameters and returns void
Function: A delegate that takes 0 to 4 parameters and returns a T
(Shamelessly copied from Jon Skeet's Answer here)
So predicate is just the name given for a delegate, so that you don't have to specify it yourself.
If you have ANY function in your assembly with the signature
"bool YourFunction(string something)", it is a Predicate<string> and can be passed into any other function that takes one:
public bool SomeFunctionUsedAsPredicate(string someInput)
{
// Perform some very specific functionality, i.e. calling a web
// service to look up stuff in a database and decide if someInput is good
return true;
}
// This Function is very generic - it does not know how to check if someInput
// is good, but it knows what to do once it has found out if someInput is good or not
public string SomeVeryGenericFunction(string someInput, Predicate<string> someDelegate)
{
if (someDelegate.Invoke(someInput) == true)
{
return "Yup, that's true!";
}
else
{
return "Nope, that was false!";
}
}
public void YourCallingFunction()
{
string result = SomeVeryGenericFunction("bla", SomeFunctionUsedAsPredicate);
}
The whole point is separation of concerns (see the comment in SomeGenericFunction) and also to have very generic functions. Look at my generic, extensible string encoding function. This uses the Func rather than the Predicate delegate, but the purpose is the same.
look at it like this:
foreach(string s in b)
{
if(a.Contains(s))
b.Remove(s);
}
You passing the bit in the if evaluation clause as a delegate (managed equivalent of a function pointer). The RemoveAll method unrolls the list and does the rest.
It says 'remove all elements in b that are contained in a'. So you're left only with the one's in b that weren't also present in a.
Here is a slightly expanded version of your code that shows what's happening:
List<string> a = new List<string> () { "a", "b", "c" };
List<string> b = new List<string> () { "a", "b", "c", "d", "e", "f" };
Predicate<string> ps = a.Contains;
b.RemoveAll (ps);
For every element in b, a.Contains() is being evaluated for that element. If it's true, it is removed.
So, you're removing every element from b that is also contained in a.
The function "a.Contains" is being passed as an argument to RemoveAll.
The signature for RemoveAll looks like this ...
public int RemoveAll(Predicate<T> match);
A Predicate<T> is a delegate that takes Ts and returns bools ...
public delegate bool Predicate<T>(T obj)
RemoveAll is thus asking for a reference to a method that will, in your case, take strings and return bools. List<T>.Contains is such a method. You will note that the signature for List<T>.Contains matches the Predicate delegate (it takes Ts and returns bools) ...
public bool Contains(T item);
RemoveAll will apply whatever Predicate is passed as "match" to each element of the list upon which it is called (b in your case). So, if a.Contains("a"), for example, returns true, then all the a's will be removed from the b list. Thus, in your example, all the a's, b's and c's are removed.
Using a tool like .NET Reflector will let you look at the code of RemoveAll and that might help clarify what's happening under the covers.