Unable to subtract a list from another list using .Except - c#

I have the following code inside my asp.net mvc-5 & ET-6 :-
List<String> ScannedResourceNames = new List<String>();
if (scaninfo.Any(a => a.VMList.Any(a2 => a2.Resource.RESOURCENAME.ToLower() == vmname.ToLower())))
{
ScannedResourceNames.Add(vmname.ToLower());
}
List<String> allcurrentresourcename = scaninfo.SelectMany(a => a.VMList.Select(a2 => a2.Resource.RESOURCENAME)).ToList();
List<String> finallist = allcurrentresourcename.Except(ScannedResourceNames).ToList();
currently the allcurrentresourcename have 3 items :
A
B
C
while ScannedResourceName have 1 item :
B
So i though when i define .Except i will get 2 items (A& C) in the finallist var. but the final list will have 3 items (A,B,C). so can anyone advice on this please ?

You can use one of the standard StringComparer properties to ignore case.
List<String> finallist = all.Except(these, StringComparer.InvariantCultureIgnoreCase)
.ToList();

Probably related to case, because when you fill the ScannedResourceNames list you're ignoring it:
a2.Resource.RESOURCENAME.ToLower() == vmname.ToLower()))
But Except uses the Equals implementation which is case-sensitive.
If you don't want to use the comparer, that should do the trick too:
List<String> finallist = allcurrentresourcename.Where(r =>
!ScannedResourceNames.Contains(r.ToLower())
.ToList();

Related

How Enumerable.Zip works with LinQ

I would like to Zip multiple List of integer and don't know how to do that in LinQ.
Here's my List :
List<KeyValuePair<Guid, List<int>>> totals = Totals.Where(x => x.Key == myGuid).ToList();
//where Totals is a List<KeyValuePair<Guid, List<int>>>
List<List<int>> totalsValue = totals.Select(s => s.Value).ToList();
//I want to Zip all my List<int> in totalsValue and put it into listToReturn
List<int> listToReturn = new List<int>();
I want something like that : http://linqsamples.com/linq-to-objects/other/Zip-lambda-csharp but in this exemple, lists are separeted.
Mine is a List>
Where listToReturn represents the list to return.
Can someone help me ?
Result :
Where adventest is a List and agiltest also
enter image description here
I think you are looking for SelectMany:
List<int> listToReturn= totals = Totals.Where(x => x.Key == myGuid)
.SelectMany(s => s.Value)
.ToList();
What you are trying to do is flatten all the lists into one sequence and that is what SelectMany extension method do. Zip, in the other side, merges each element of the first sequence with an element that has the same index in the second sequence, in other words, it allows you to project from two sequences of the same length.
Update
Now I understand what you are trying to achieve:
var lists= Totals.Where(x => x.Key == myGuid).Select(e=>Value).ToList();// Select the lists
if(lists.Count>0)
var result= Enumerable.Range(0, lists[0].Count).Select(i=> lists.Sum(l=>l[i]));
The thing with this solution you need to make sure that all the selected lists have the same size. I'm pretty sure there is a more elegant solution but this was that come to my mind now. If I think in something better I will update my answer

Use LINQ to search items in a SortedDictionary

I have a SortedDictionary of the type:
SortedDictionary<PriorityType, List<T>> dictionary;
where PriorityType is an Enum class, and the List contains various string values.
I want to use LINQ to search for the string items in the list, that have an even length.
As in:
IEnumerable<T> filteredList = new List<T>();
// Stores items in list whose string length is even
filteredList = //LINQ code;
I have tried a lot of implementations of LINQ but, it seems tough to traverse a List in a SortedDictionary using LINQ (taking into account I'm relatively new to LINQ).
Please help me with the LINQ code. Thanks!
If I understand you correctly, then you need items from lists which have even count of items:
filteredList = dictionary.Select(kvp => kvp.Value)
.Where(l => l != null && l.Count % 2 == 0)
.SelectMany(l => l)
.ToList();
UPDATE: If you want to select strings with even length, then you should use List<string> instead of generic list of T:
SortedDictionary<PriorityType, List<string>> dictionary;
filteredList = dictionary.SelectMany(kvp => kvp.Value)
.Where(s => s.ToString().Length % 2 == 0)
.ToList();
The solution provided by #Sergey is correct & in conformance to my requirements.
Also I found another easy solution using the select statement.
filteredList = from list in dictionary.Values from item in list where item.ToString().Length % 2 == 0 select item;
Hope this helps!

C# Object List to String List

I have List<object> that seems above, I want to convert it to List<string>.
How can I convert it ?
I need List<string> that has 6 items (11:00,13:45,.... etc)
var mylist = myObjectList.ConvertAll(x => x.ToString());
Edit
var mylist = myObjectList.ConvertAll(x => Convert.ToString(x));
thanks Scott Chamberlain
To get first array of objects
var mylist = (myObjectList.First() as object[]).ToList()
.ConvertAll(x=>Convert.ToString(x));
To add rest to the list.
mylist.AddRange(mylist.GetRange(1,myObjectList.Count-2).ConvertAll(x=>Convert.ToString(x)));
var stringList = yourObjectList.OfType<string>().ToList();
Remember to add the namespace System.Linq;
The OfType is needed to convert the array to an array<T> which is necessary in order to use it with LINQ
Try this
List<string> stringlist = objectList.Cast<string>()
.ToList();
If you're not certain about those elements are strings you can use Select
List<string> stringlist = objectList.Select(x=> x.ToString())
.ToList();
To avoid NullReferenceException in case of null values try the following
List<string> stringlist = objectList.Where(x=> x != null)
.Select(x=> x.ToString())
.ToList();
Using LINQ this is fairly easy. If you are sure they are all strings you can simply do
int i = //Some code that sets i, like a for loop
var oldList = seanceInfo.theatre[i].seances;
List<string> newList = oldList.Cast<string>().ToList();
If you are not sure all of the objects are strings you need to perform some kind of conversion, however that is just as easy
List<string> newList = oldList.Select(o => Convert.ToString(o)).ToList();
From your comment: "seances is List<object>, and first index of seances is object[]. I need these items.", I think what you really want may be a SelectMany
List<string> info = seanceInfo.theatre.SelectMany(x => x.seances).Select(x => Convert.ToString(x)).ToList();
This will take each seance in each theater and combine it in to one master list.
You can simply cast it using LinQ.
myObjectList.Cast<string>();
Or filter all non-string
myObjectList.OfType<string>();
Casting like :
var list = (List<String>) listObjects.

How to find duplicates in list and sort them by number of appearance

Is there a easy way to find duplicates in list, and then sort them by number of appearance? Also, duplicates should be removed.
Eg. you have a List<String> like this:
List<String> = new List<String>{"6","1","2","2","4","6","5","1","6","6","2"};
Question is, how to convert this list into -> "6", "1", "2", "4", "5"?
use Linq.Distinct()
List<String> list = new List<String>{"6","1","2","2","4","6","5","1","6","6","2"};
list = list.Distinct().ToList();
If you actually want them ordered from most common to least - unlike your example -
var ordered = list
.GroupBy(i => i)
.OrderByDescending(g => g.Count())
.Select(g => g.Key);
should achieve this.
I think the simplest way is to use LINQ method Distinct():
var originalList = …;
vat withoutDuplicates = originalList.Distinct();
Though you should note that the order of the result of Distinct() is explicitly left undocumented.
Using System.Linq;
// Assuming inputList was the original string list
List<String> deDuped = inputList.Distinct().ToList();
Not quite the cleanest yet, but this provides the correct result.
var originalData = new List<string>{"6","1","2","2","4","6","5","1","6","6","2"};
var result = new List<string>();
foreach (var myString in originalData)
{
if (!result.Exists(s => s == myString))
result.Add(myString);
}
Since it's unclear exactly what you mean, here's a solution for two possible meanings:
Get a unique list ordered by the number of occurrences:
Group the list and sort by Count():
List<String> list = new List<String>{"6","1","2","2","4","6","5","1","6","6","2"};
var q = from s in list
group s by s into g
orderby g.Count() descending
select g.Key;
Get a unique list ordered by the FIRST occurrence of the item in the list
There are already several suggestions to use Distinct, however the documentation DOES NOT GUARANTEE that they appear in the order they appear in the list (the current Enumerable implementation happens to order them that way, but for other providers it's not guaranteed):
Remarks
The result sequence is unordered.
To guarantee order, add an OrderBy clause:
var q = list.Distinct().OrderBy(s => list.IndexOf(s));

Remove items from one list in another

I'm trying to figure out how to traverse a generic list of items that I want to remove from another list of items.
So let's say I have this as a hypothetical example
List<car> list1 = GetTheList();
List<car> list2 = GetSomeOtherList();
I want to traverse list1 with a foreach and remove each item in List1 which is also contained in List2.
I'm not quite sure how to go about that as foreach is not index based.
You can use Except:
List<car> list1 = GetTheList();
List<car> list2 = GetSomeOtherList();
List<car> result = list2.Except(list1).ToList();
You probably don't even need those temporary variables:
List<car> result = GetSomeOtherList().Except(GetTheList()).ToList();
Note that Except does not modify either list - it creates a new list with the result.
You don't need an index, as the List<T> class allows you to remove items by value rather than index by using the Remove function.
foreach(car item in list1) list2.Remove(item);
In my case I had two different lists, with a common identifier, kind of like a foreign key.
The second solution cited by "nzrytmn":
var result = list1.Where(p => !list2.Any(x => x.ID == p.ID && x.property1 == p.property1)).ToList();
Was the one that best fit in my situation.
I needed to load a DropDownList without the records that had already been registered.
Thank you !!!
This is my code:
t1 = new T1();
t2 = new T2();
List<T1> list1 = t1.getList();
List<T2> list2 = t2.getList();
ddlT3.DataSource= list2.Where(s => !list1.Any(p => p.Id == s.ID)).ToList();
ddlT3.DataTextField = "AnyThing";
ddlT3.DataValueField = "IdAnyThing";
ddlT3.DataBind();
I would recommend using the LINQ extension methods. You can easily do it with one line of code like so:
list2 = list2.Except(list1).ToList();
This is assuming of course the objects in list1 that you are removing from list2 are the same instance.
list1.RemoveAll(l => list2.Contains(l));
You could use LINQ, but I would go with RemoveAll method. I think that is the one that better expresses your intent.
var integers = new List<int> { 1, 2, 3, 4, 5 };
var remove = new List<int> { 1, 3, 5 };
integers.RemoveAll(i => remove.Contains(i));
Solution 1 : You can do like this :
List<car> result = GetSomeOtherList().Except(GetTheList()).ToList();
But in some cases may this solution not work. if it is not work you can use my second solution .
Solution 2 :
List<car> list1 = GetTheList();
List<car> list2 = GetSomeOtherList();
we pretend that list1 is your main list and list2 is your secondry list and you want to get items of list1 without items of list2.
var result = list1.Where(p => !list2.Any(x => x.ID == p.ID && x.property1 == p.property1)).ToList();
As Except does not modify the list, you can use ForEach on List<T>:
list2.ForEach(item => list1.Remove(item));
It may not be the most efficient way, but it is simple, therefore readable, and it updates the original list (which is my requirement).
I think it would be quick to convert list A to a dictionary and then foreach the second list and call DictA.Remove(item) otherwise I think most solutions will cause many iterations through list A either directly or under the covers.
If the lists are small, it probably won't matter.
In case you have two different list with different DataModals
List<FeedbackQuestionsModel> feedbackQuestionsList = new();
List<EmployeesFeedbacksQuestionsModel> employeeQuestionsList = new();
var resultList = feedbackQuestionsList.Where(p => !employeeQuestionsList.Any(x => x.Question == p.Question)).ToList();
feedbackQuestionsList = resultList.ToList();
Here ya go..
List<string> list = new List<string>() { "1", "2", "3" };
List<string> remove = new List<string>() { "2" };
list.ForEach(s =>
{
if (remove.Contains(s))
{
list.Remove(s);
}
});

Categories

Resources