Removing certain elements from list condition based on another list - linq

I am having a basic issue here with linq . Though this can be solved with repeated loops . I am trying to know how can this be done in linq .
I have two lists .
List<string> a = new List<string>{"a","b","c","d","e","f"};
List<string> b = new List<string> { "a", "b", "c", "x", "y", "z" };
I want to compare with list a and whichever element in b is found in a . I want to remove that element from b . In other words I want to remove {"a","b","c"} from b based on comparison from list a and want to contain only {"x","y","z"} in list b . Is there a single statement linq to solve this ?

(I'm sure this is a duplicate of another post just a few days ago, but I can't find it...)
If you need a modification in place, you can use List<T>.RemoveAll:
b.RemoveAll(x => a.Contains(x));
Or more efficiently (if the lists are large):
HashSet<string> set = new HashSet<string>(a);
b.RemoveAll(set.Contains);
Note that modifying a collection in place isn't idiomatic in LINQ, which is why the above uses the .NET 2 list-specific method.
Or if you're happy to change b to refer to a new list instead, then you can use LINQ:
b = b.Except(a).ToList();

Related

Select more than one item by index position in a M / PowerQuery list?

Let's say I have the following list in M language: {"A", "B", "C" } and I want to select more than one item. How can I do it? When I check the M language specs it only shows examples on how to select one item through the following syntax {list}{#index} but that only retrieves a single item. I tried using the : operator as in other languages without success.
You could pull specific items in the list like this, position 2,1,4
= List.Combine ({ {{list}{2}}, {{list}{1}}, {{list}{4}} })
Or you could pick a range with List.Range see List.Range
Or pick out one of the other List.xxx functions in list functions

Difficulty Accessing Members of Tuple in Apache Pig

I have a variable titled F.
Describe F returns:
F: {group: bytearray,indexkey: {(indexkey: chararray)}}
Dump F returns:
(321,{(CHOW),(DREW)})
(5011,{(CHOW),(DREW)})
(5825,{(TANNER),(SPITZENBERGER)})
(16631,{(CHOW),(DREW)})
(34299,{(CHOW),(DREW)})
(35044,{(TANNER),(SPITZENBERGER)})
(65623,{(CHOW),(DREW)})
(74597,{(SPITZENBERGER),(TANNER)})
(83499,{(SPITZENBERGER),(TANNER)})
(90257,{(SPITZENBERGER),(TANNER)})
What I need is to produce an output that looks like this (only 1st row as an example):
(321,DREW,{(CHOW)})
I've tried using deference to pull out the first element by using this:
G = FOREACH F generate indexkey.$0;
But, this still returns the whole tuple.
Can anyone suggest a method for doing this? I was under the impression that the deference operator should allow me to do this.
Thanks in advance!
Daniel
You can't index into bags like that. The reason for that is bags don't have any notion of ordering. Selecting the first item in a bag should be treated as picking a random one.
Either way, if you want only one item instead of all of them you can used a nested FOREACH to pull a LIMIT of 1:
first = FOREACH F {
lim = LIMIT indexkey 1;
GENERATE group, lim;
}
(disclaimer: I can't test this code right now, if it doesn't work let me know. Hopefully you can get the gist)
You can take this a bit further and FLATTEN it to remove the bag of one item entirely, but be careful in that if the bag is empty i think you throw away the entire record in this case.
first = FOREACH F {
lim = LIMIT indexkey 1;
GENERATE group, FLATTEN(lim);
}

take two arrays and make a third array from values that are NOT unique

I'm attempting to de-dupe an enormous email list migration, however there's a catch. I'd like to take the duplicates and turn them into their own array (3rd).
Lets make these arrays very simple, and short.
a = ["rich#aol.com", "ian#aol.com"]
b = ["rich#aol.com"]
Essentially i'm trying to make c = ["rich#aol.com"] because it's the only email that resides on both lists.
What I've attempted so far:
Is there an opposite to unqiq ?
ab = a + b
ab.uniq
returns: ["rich#aol.com", "ian#aol.com"]
Could I dump a + b into a third c array, and compare c to ab.uniq to get what's duplicated?
Am i missing an easier way to do this? Any help will be much appreciated!!!!
You want the intersection of the arrays.
c = a & b

Filter a list and get also its opposite with linq

I have a simple question about list with LINQ. I searched about it and I haven't found anything like it.
I don't know which of them is better (in performance, for example).
list1 = list.Where(x => x.property).ToList();
Now I want the opposite list
list2 = list.Where(x=> !x.property).ToList();
I used this, but I am not sure.
list2 = list.Except(list1).ToList();
I've also thought getting a group and get both lists at the same time. It is a list with two lists. Iterate over the first list is heavy.
What do you think about it?
Thanks a lot.
Honestly, I'd just go with:
var listEqual = new List<YourType>();
var listNotEqual = new List<YourType>();
foreach(YourType item in list)
if (item.Property)
listEqual.Add(item)
else
listNotEqual.Add(item);
You could use
var lookup = list.ToLookup(x => x.Property);
var list1 = lookup[true].ToList();
var list2 = lookup[false].ToList();
(even dropping the ToList if you don't strictly need lists) - this does only iterate your sequence once, although you need a little more code to handle the case where everything in your input is either true or false.

matching array items in rails

I have two arrays and I want to see the total number of matches, between the arrays individual items that their are.
For example arrays with:
1 -- House, Dog, Cat, Car
2 -- Cat, Book, Box, Car
Would return 2.
Any ideas? Thanks!
EDIT/
Basically I have two forms (for two different types of users) that uses nested attributes to store the number of skills they have. I can print out the skills via
current_user.skills.each do |skill| skill.name
other_user.skills.each do |skill| skill.name
When I print out the array, I get: #<Skill:0x1037e4948>#<Skill:0x1037e2800>#<Skill:0x1037e21e8>#<Skill:0x1037e1090>#<Skill:0x1037e0848>
So, yes, I want to compare the two users skills and return the number that match. Thanks for your help.
This works:
a = %w{house dog cat car}
b = %w{cat book box car}
(a & b).size
Documentation: http://www.ruby-doc.org/core/classes/Array.html#M000274
To convert classes to an array using the name, try something like:
class X
def name
"name"
end
end
a = [X.new]
b = [X.new]
(a.map{|x| x.name} & b.map{|x| x.name}).size
In your example, a is current_user.skills and b is other_users.skills. x is simply a reference to the current index of the array as the map action loops through the array. The action is documented in the link I provided.

Resources