LINQ - Compare List objects and List of strings - c#

I have a list of objects (List1) and list of string (List2 - list of Names of the objects)
I need to get all objects from List1 if the object.Name does not exists in List2
How can write this LINQ C#.?

public class Class1
{
public string Name {get;set;}
}
var List1 = new List<Class1>();
var List2 = new List<string>();
var result = List1.Where(x=>!List2.Contains(x.Name)).ToList();
Or:
var result = List1.Where(x=>!List2.Any(n=>n==x.Name)).ToList();

class Program
{
static void Main(string[] args)
{
List<List1Class> listClass = new List<List1Class>();
listClass.Add(new List1Class { ObjectName = "obj1" });
listClass.Add(new List1Class { ObjectName = "obj2" });
listClass.Add(new List1Class { ObjectName = "obj3" });
listClass.Add(new List1Class { ObjectName = "obj4" });
List<string> listString = new List<string>();
listString.Add("obj2");
listString.Add("obj4");
listString.Add("obj5");
var filterlist = listClass.Where(l => !listString.Contains(l.ObjectName)).ToList();
}
}
class List1Class
{
public string ObjectName { get; set; }
//Add other property
}

Related

How to convert List<string> to List<object> specific property in C#

How to convert List<string> to List<object> property in c#
We have a list of email id's
List<string> str= new List<string>{"abc1#gmail.com","abc2#gmail.com"};
and now we have to assign these email IDs to the list of an employee List<Employee> emailId property.
var emplist = new List<Employee>() ;
You can use Select().
var emplist = str.Select(x => new Employee { EmailId = x }).ToList();
Select() is used for projecting each element of a sequence(in your case it is string email id) into a new sequence i.e. the Employee object.
We can convert or assign List<string> to List<object> to specific property
//here Employee is an Object type
public static void Main(string[] args)
{
List<string> list = new List<string>() { "abc1#gmail.com", "abc2#gmail.com" } ;
var emplist= new List<Employee>() ;
if(list.Any())
list.ForEach(str => emplist.Add(new Employee { EmailId = str }));
Console.ReadLine();
}
public class Employee {
public string EmailId { get; set; }
public string Address { get; set; }
}

Deserialise JSON to C# array, where index is in the property name

Could anyone provide their approach for deserializing the following JSON
{
"i": 5
"b0": "ABC",
"b1": "DEF",
"b2": "GHI",
"s0": "SABC",
"s1": "SDEF",
"s2": "SGHI",
}
into a class in C# to provide the same structure as this
class Example {
public int Index {get;set;}
public string[] B {get;set;}
public string[] S {get;set;}
}
var b = new [] {"ABC", "DEF", "GHI"}
var s = new [] {"SABC", "SDEF", "SGHI"}
I generally use ServiceStack.Text, but Json.Net approach or even a BsonDocument from the MongoDb provider is fine.
Could use a JToken and use .Values() then .ToArray():
var json = "{\r\n \"b0\": \"ABC\",\r\n \"b1\": \"DEF\",\r\n \"b2\": \"GHI\",\r\n}";
var token = JToken.Parse(json);
var b = token.Values().ToArray();
This one solution might be useful too:
public class Example
{
public int Index { get; set; }
public string[] B { get; set; }
public string[] S { get; set; }
}
var strData = #"{'i': 5, 'b0': 'ABC','b1': 'DEF', 'b2': 'GHI', 's0': 'SABC', 's1': 'SDEF', 's2': 'SGHI',}";
var data = JsonConvert.DeserializeObject<JToken>(strData).Values().ToList();
Example result = new Example();
result.Index = data.Values().FirstOrDefault(x => x.Path == "i").Value<int>();
result.B = data.Values().Where(x => x.Path.StartsWith("b")).Select(x => x.Value<string>()).ToArray();
result.S = data.Values().Where(x => x.Path.StartsWith("s")).Select(x => x.Value<string>()).ToArray();
there is solution for dynamic name of arrays, but string array is not the best type in this case:
public class Example
{
public int Index { get; set; }
public Dictionary<string, string[]> Data { set; get; }
}
var s = #"{'i': 5, 'b0': 'ABC','b1': 'DEF', 'b2': 'GHI', 's0': 'SABC', 's1': 'SDEF', 's2': 'SGHI',}";
var data = JsonConvert.DeserializeObject<JToken>(s).Values().ToList();
Example result = new Example();
result.Index = data.Values().FirstOrDefault(x => x.Path == "i").Value<int>();
result.Data = new Dictionary<string, string[]>();
var stringData = data.Values().Where(x => x.Path != "i").ToList();
stringData.ForEach(x =>
{
var key = x.Path[0].ToString();
if (!result.Data.ContainsKey(key))
{
result.Data.Add(key, new string[0]);
}
var currentValue = result.Data[key].ToList();
currentValue.Add(x.Value<string>());
result.Data[key] = currentValue.ToArray();
});

How to get intersection of two classes based on property

I have this class
public class FlightSegment{
public string ClassName { get;set;}
}
And I want to get FlightSegments with common ClassName
void Main()
{
var list1 = new List<FlightSegment>() {
new FlightSegment{ ClassName = "A"},
new FlightSegment { ClassName = "B"}
};
var list2 = new List<FlightSegment>() {
new FlightSegment{ ClassName = "B"},
new FlightSegment { ClassName = "C"}
};
var listOfLists = new List<List<FlightSegment>>() { list1, list2 };
var intersection = listOfLists.Aggregate((previousList, nextList) => previousList.Intersect(nextList).ToList());
Console.WriteLine(intersection); //Gives me empty result
}
I tried something like this:
var intersection = listOfLists.Aggregate((previousList, nextList) =>
previousList.Select(e=>e.ClassName).Intersect(nextList.Select(e=>e.ClassName)).ToList());
But gives error:
Cannot convert expression type System.Collection.Generic.List<string> to return type System.Collection.Generic.List<FlightSegment>
You can use Intersect method passing a IEqualityComparer to compare according to ClassName property:
class FlightComparer : EqualityComparer<FlightSegment>
{
public override bool Equals(FlightSegment x, FlightSegment y)
{
return x.ClassName == y.ClassName;
}
public override int GetHashCode(FlightSegment obj)
{
return obj.ClassName.GetHashCode();
}
}
Then, make the intersection using this comparer:
var list1 = new List<FlightSegment>() {
new FlightSegment{ ClassName = "A"},
new FlightSegment { ClassName = "B"}
};
var list2 = new List<FlightSegment>() {
new FlightSegment{ ClassName = "B"},
new FlightSegment { ClassName = "C"}
};
var result = list1.Intersect(list2, new FlightComparer());
This returns a collection containing only one element FlightSegment { ClassName = "B" }.
Using this idea and Aggregate, you can get the intersection of a group of lists based on a property:
var intersection = listOfLists.Aggregate((previousList, nextList) => previousList.Intersect(nextList, new FlightComparer() ).ToList());

Select an attribute from object in a List inside another List

Can I perform a select using ternary operator to get an attribute from object inside a list?
Here is my model:
public class Xpto
{
public List<Son> Sons { get; set; }
}
public class Son
{
public string Names { get; set; }
}
And here i would like to get "Name" attribute for each son that i have:
var result = (from a in mylist
select new
{
sonsNames = a.Sons == null : <What should i put here?>
}).ToList<object>();
I've tried Sons.ToString() but it prints an object reference.
I would like to have a string list in "sonsNames" and each name separeted by a ','. Example: sonsName: 'george, john'.
what about this ?
//set up a collection
var xptos = new List<Xpto>()
{ new Xpto()
{ Sons = new List<Son>
{ new Son() { Names = "test1" },
new Son() { Names = "test2" }
}
},
new Xpto()
{
Sons = new List<Son> {
new Son() { Names = "test3" }
}
}};
//select the names
var names = xptos.SelectMany(r => r.Sons).Where(k => k.Names != null)
.Select(r => r.Names + ",") .ToList();
names.ForEach(n => Console.WriteLine(n));
Here's more info on SelectMany()

I cannot add Multiple data into my list<string>

I have the following list:
List<string> department = new List<string>();
Add the data one by one is working but I cannot push the multiple data into the list:
using System;
namespace Linq_Basics
{
class Program
{
static void Main(string[] args)
{
List<names> names = new List<names>();
names.Add(new names { Firstname = "viki", Lastname = "Amar" });
names.Add(new names { Firstname = "Sankar", Lastname = "Pandi" });
names.Add(new names { Firstname = "Bala", Lastname = "Murugan" });
foreach (var v in names)
{
Console.WriteLine("The Firstname is {0} and the last name is {1}", v.Firstname, v.Lastname);
}
List<string> department = new List<string>();
department.Add(new List<string> { "ece", "cse" });
Console.ReadKey();
}
}
class names
{
public string Firstname { get; set; }
public string Lastname { get; set; }
}
}
Use List<T>.AddRange method to add sequence of strings to list of strings:
department.AddRange(new List<string> { "ece", "cse" });
Or simply call Add twice to avoid new list creation:
department.Add("ece");
department.Add("cse");
Or use collection initializer if you want to hold only these two strings in department list:
var department = new List<string> { "ece", "sce" };
List<string> department = new List<string> { "ece", "cse" };
department defines a list which holds the string type. You are trying to add a List<string> to it instead of a string:
List<string> department = new List<string>();
department.Add(new List<string> { "ece", "cse" });
Needs to be:
department.Add("ece")
//etc...
Or:
department = new List<string>() { "ece", "cse" };
Or:
department.AddRange(new List<string> { "ece", "cse" });

Categories