There are two lists:
List<string> excluded = new List<string>() { ".pdf", ".jpg" };
List<string> dataset = new List<string>() {"valid string", "invalid string.pdf", "invalid string2.jpg","valid string 2.xml" };
How can I filter-out values from the "dataset" list which contain any keyword from the "excluded" list?
var results = dataset.Where(i => !excluded.Any(e => i.Contains(e)));
// Contains four values.
int[] values1 = { 1, 2, 3, 4 };
// Contains three values (1 and 2 also found in values1).
int[] values2 = { 1, 2, 5 };
// Remove all values2 from values1.
var result = values1.Except(values2);
https://www.dotnetperls.com/except
Try:
var result = from s in dataset
from e in excluded
where !s.Contains(e)
select e;
var result=dataset.Where(x=>!excluded.Exists(y=>x.Contains(y)));
This also works when excluded list is empty.
var result = dataset.Where(x => !excluded.Contains(x));
Related
I have this enum :
public enum MyEnum
{
A = 0,
B = 1,
C = 2,
D = 3,
E = 4
}
I have a List<string> {"A", "C", "E"}
I'd like make a query on MyEnum to get back the int values as a List<int> Here the result should be 0,2,4
Same question but when I have a List<int> {0, 2, 4} I'd like get back a List<string> with A,C,E
Do you have an idea how do this in .NET 4.7 ?
Thanks,
If you are sure they exist you can parse them and use List.ConvertAll:
List<string> list = new() { "A", "C", "E" };
List<int> result = list.ConvertAll(s => (int)(MyEnum)Enum.Parse(typeof(MyEnum), s));
to get the strings back, so the opposite way:
list = result.ConvertAll(i => ((MyEnum)i).ToString());
From names to values:
using System.Linq;
...
List<string> names = new List<string>() { "A", "C", "E" };
// If there's no guarantee that name is a correct enum name
// use TryParse instead of Parse
var values = names
.Select(name => Convert.ToInt32(Enum.Parse(typeof(MyEnum), name)))
.ToList();
From values to names:
using System.Linq;
...
List<int> values = new List<int>() { 0, 2, 4 };
var names = values
.Select(value => ((MyEnum)value).ToString())
.ToList();
Please, fiddle
I have a class where it has a collection of list. I want to search a parameter inside one of the list. So the location that I found the list, I want to get at the same location at other list in the same class...
How to achieve this?
void Main()
{
var myListCollectionObj = new myListCollection();
Console.WriteLine(myListCollectionObj.firstList);
Console.WriteLine(myListCollectionObj.secondList);
Console.WriteLine(myListCollectionObj.thirdList);
var testFirstList = myListCollectionObj.firstList.Where(x => x == 3); //then i want to get "33", and 333 from secondList and thirdList respectively
Console.WriteLine(testFirstList);
}
class myListCollection
{
public List<int> firstList = new List<int>(){ 1, 2, 3, 4, 5};
public List<string> secondList = new List<string>(){ "11", "22", "33", "44", "55"};
public List<int> thirdList = new List<int>(){ 111, 222, 333, 444, 555};
}
int index = myListCollectionObj.firstList.IndexOf(3);
string elem2;
int elem3;
if (index >= 0 && index < myListCollectionObj.secondList.Length)
elem2 = myListCollectionObj.secondList[index]
if (index >= 0 && index < myListCollectionObj.thirdList.Length)
elem3 = myListCollectionObj.thirdList[index]
You don't need LINQ for that, only List<T>'s own IndexOf() method and indexer property:
int index = myListCollectionObj.firstList.IndexOf(3);
string secondValue = myListCollectionObj.secondList[index];
int thirdValue = myListCollectionObj.thirdList[index];
You may want to add error handling: if 3 is not contained in firstList, an index of -1 is returned by IndexOf().
I guess the best way if there are more than one 3 values would be using simple for loop:
var testFirstList = new List<int>();
var testSecondList = new List<string>();
var testThirdList = new List<int>();
for (var i = 0; i < myListCollectionObj.firstList.Length; ++i) {
if (myListCollectionObj.firstList[i] == 3) {
testFirstList.Add(myListCollectionObj.firstList[i]);
testSecondList.Add(myListCollectionObj.secondList[i]);
testThirdList.Add(myListCollectionObj.thirdList[i]);
}
}
A good guideline is that if you find yourself combining indices and LINQ, you probably have other options available. In this case, a good alternative would be using Zip
This approach lets you combine the 3 collections and act upon the resulting zipped collection as a single entity such that indices are no longer directly required.
var result = firstList.Zip(
secondList.Zip(thirdList,
(b, c) => new { b, c }),
(a, b) => new { Value1 = a, Value2 = b.b, Value3 = b.c })
.Where(x => x.Value1 == 3).ToList();
result.ForEach(v => Console.WriteLine(v));
correct me if i am wrong are you looking for the index of the item you searched in first list and then use the same index to retrieve from other list
If yes
Try this
var testFirstList = myListCollectionObj.firstList.Where(x => x == 3).FirstOrDefault(); //then i want to get "33", and 333 from secondList and thirdList respectively
var index = myListCollectionObj.firstList.IndexOf(testFirstList);
List<String> A = new List<String>();
List<String> B = new List<String>();
List<String> itemsremoved = ((A∩B)^c)-A;
List<String> itemsadded = ((A∩B)^c)-B;
I want to know how to do a complement of the union A & B minus the elements of a list. Is there a function to do this?
LINQ provides extension methods for working with sets.
For example, the complement of set a relative to set b will be:
var a = new List<int> { 1, 2, 3, 6 };
var b = new List<int> { 3, 4, 5, 6 };
var comp = a.Except(b);
comp will contain elements [1, 2].
Do a Google search for C# and LINQ set operations and you're sure to find plenty of examples.
Suppose I have two Lists<myObject> where myObject consists of the two properties
Id (of type Int) and
Value (of type Double)
I need to get a list out of these two lists that is made of (anonymous) objects like this:
Id, [Double value from List 1], [Double value from List 2]
So if for a given Id both lists contain a value, it should look like this example:
12, 21.75, 19.87
If one list does not contain an object with an Id that is present in the other list, the value should be null:
15, null, 22.52
How can I achieve that?
Update: I know how I could get such a list, of course, but I'm looking for the most performant way to do it, preferrably by using some witty Linq magic.
Not sure how optimized this is, but should suit your needs - Assuming I understood what you wanted:
var enumerable1 = new[]
{
new {Id = "A", Value = 1.0},
new {Id = "B", Value = 2.0},
new {Id = "C", Value = 3.0},
new {Id = "D", Value = 4.0},
new {Id = "E", Value = 5.0},
};
var enumerable2 = new[]
{
new {Id = "A", Value = 6.0},
new {Id = "NOT PRESENT", Value = 542.23},
new {Id = "C", Value = 7.0},
new {Id = "D", Value = 8.0},
new {Id = "E", Value = 9.0},
};
var result = enumerable1.Join(enumerable2, arg => arg.Id, arg => arg.Id,
(first, second) => new {Id = first.Id, Value1 = first.Value, Value2 = second.Value});
foreach (var item in result)
Console.WriteLine("{0}: {1} - {2}", item.Id, item.Value1, item.Value2);
Console.ReadLine();
The resulting output would be something akin to:
A: 1 - 6
C: 3 - 7
D: 4 - 8
E: 5 - 9
Don't really see why you would want null values returned, unless you absolutely need to (Besides, double is not-nullable, so it would have to be the resulting combined entry that would be null instead).
The requirement is slightly unclear. Do you want a Cartesian product or a join on Id? If the latter, then this should work:
var result = from l1 in list1
join l2 in list2
on l1.Id equals l2.Id
select new {l1.Id, Value1 = l1.Value, Value2 = l2.Value};
If you actually want a full outer join, see this.
**Let say tempAllocationR is list 1 and tempAllocationV is List2 **
var tempAllocation = new List<Object>();
if (tempAllocationR.Count > 0 && tempAllocationV.Count > 0)
{
foreach (TempAllocation tv in tempAllocationV)
{
var rec = tempAllocationR.FirstOrDefault(tr => tr.TERR_ID == tv.TERR_ID && tr.TERR == tv.TERR && tr.Team == tv.Team);
if (rec != null)
{
rec.Vyzulta = tv.Vyzulta;
}
else
{
tempAllocationR.Add(tv);
}
}
tempAllocation = tempAllocationR;
}}
I have a generic list which contains member details and I have a string array of memberIds..I need to filter the list and get the results which contains all the memberIds..How can I achieve this using LINQ.
I tried the following
string[] memberList = hdnSelectedMemberList.Value.Split(',');
_lstFilteredMembers = lstMainMembers.Where(p =>memberList.Contains(p.MemberId))
.ToList();
But the above query is giving me only the results that match the first member ID..so lets say if I have memberIds 1,2,3,4 in the memberList array..the result it returns after the query contains only the members with member ID 1..even though the actual list has 1,2,3,4,5 in it..
Can you please guide me what I am doing wrong.
Thanks and appreciate your feedback.
Strings make terrible primary keys. Try trimming the list:
string[] memberList = hdnSelectedMemberList.Value
.Split(',')
.Select(p => p.Trim())
.ToList();
_lstFilteredMembers = lstMainMembers.Where(p => memberList.Contains(p.MemberId)).ToList();
Because I have a feeling hdnSelectedMemberList may be "1, 2, 3, 4".
Use a join:
var memquery = from member in lstMainMembers
join memberid in memberList
on member.MemberId equals memberid
select member;
With jmh, I'd use a join
var members = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var ids = new[] { 1, 3, 6, 14 };
var result = members.Join(ids, m => m, id => id, (m, id) => m);
foreach (var r in result)
Console.WriteLine(r); //prints 1, 3, 6
The code you are showing is correct, and works in a Unit Test:
public class Data
{
public string MemberId { get; set; }
}
[TestMethod]
public void Your_Code_Works()
{
// Arrange fake data.
var hdnSelectedMemberList = "1,2,3,4";
var lstMainMembers = new[]
{
new Data { MemberId = "1" },
new Data { MemberId = "2" },
new Data { MemberId = "3" },
new Data { MemberId = "4" },
new Data { MemberId = "5" }
};
// Act - copy/pasted from StackOverflow
string[] memberList = hdnSelectedMemberList.Split(',');
var _lstFilteredMembers = lstMainMembers.Where(p => memberList.Contains(p.MemberId)).ToList();
// Assert - All pass.
Assert.AreEqual(4, _lstFilteredMembers.Count);
Assert.AreEqual("1", _lstFilteredMembers[0].MemberId);
Assert.AreEqual("2", _lstFilteredMembers[1].MemberId);
Assert.AreEqual("3", _lstFilteredMembers[2].MemberId);
Assert.AreEqual("4", _lstFilteredMembers[3].MemberId);
}
There must be something wrong with your code outside what you have shown.
Try Enumerable.Intersect to get the intersection of two collections:
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.intersect.aspx
_lstFilteredMembers = lstMainMembers.Intersect(memberList.Select(p => p.MemberID.ToString())).ToList()
Why not just project the IDs list into a list of members?
var result = memberList.Select(m => lstMainMembers.SingleOrDefault(mm => mm.MemberId == m))
Of course, that will give you a list that contains null entries for items that don't match.
You could filter those out, if you wanted to...
result = result.Where(r => r != null)
Or you could filter it before the initial select...
memberList.Where(m => lstMainMembers.Any(mm => mm.MemberId == m)).Select(m => lstMainMembers.Single(mm => mm.MemberId == m))
That's pretty ugly, though.