Remove duplicates from the list with lists as objects - c#

I have one list with the class as a structure as below
class cl
{
public string name1{ get; set; }
public string name2{ get; set; }
public string name3{ get; set; }
public List<c2> c2List{ get; set; }
}
class c2
{
public string st1{ get; set; }
public string str2{ get; set; }
}
Now I have list of C1 class and i need to remove duplicates from that list
can any one help me how can i do it

When referencing c2List, call it similarly to the below:
var distinctList = c1.c2List.Distinct();
(Assuming that c1 is instantiated further up the code)

I think this is what your after..
var c2Items = new c2[]
{
new c2 { st1 = "value 1", str2 = "value 2" },
new c2 { st1 = "value 2", str2 = "value 1" },
new c2 { st1 = "value 1", str2 = "value 2" }
};
var parent = new cl() { c2List = new List<c2>(c2Items) };
IEnumerable<c2> distinctitems =
parent
.c2List
.GroupBy(o => new { o.st1, o.str2 })
.Select(o => o.First());

Related

Combine values from 2 object lists based on on common variable

I have two lists: List a, List b
var a1= new A
{
Name = "XYZ",
Id = "123"
};
var a2= new A
{
Name = "UVW",
Id = "567"
};
var a = new List<A>()
{
a1,
a2
};
public class A
{
public string Name{ get; set; }
public string Id{ get; set; }
}
var b1= new B
{
Location = "US",
Id = "123"
};
var b2= new B
{
Location = "IN",
Id = "567"
};
var b = new List<B>()
{
b1,
b2
};
public class B
{
public string Location{ get; set; }
public string Id{ get; set; }
}
Notice that Id is common in both A and B classes. The final goal is to have a list that contains values of members from both A and B classes:
var output = new List<AB>()
{
ab1,
ab2
}
public class AB
{
public string Id{ get; set; }
public string Name { get; set; }
public string Location { get; set; }
}
Or update List a to include values from List b?
How would I do that in C#?
You could use Join to get common data based on Id and populate AB, like the following code :
var output = aList.Join(bList,
a => a.Id,
b => b.Id,
(a, b) => new AB
{
Id = a.Id,
Location = b.Location,
Name = a.Name
}).ToList();
Demo
foreach(var item in output)
{
Console.WriteLine($"Id:{item.Id}, Name : {item.Name}, Location:{item.Location}");
}
Result:
Id:123, Name : XYZ, Location:US
Id:567, Name : UVW, Location:IN
Demo in dotnetfiddle : https://dotnetfiddle.net/3ZbK6c
I hope you find this helpful.

Various ways to combine two different result sets and do the iteration and sum

Here I have a class List1 and classes List2,ListViewModel for combining two datasets, and I have two different result sets, each list having four values and I need to combine them as a single resultset with 4 rows and need to do the iteration and summation by using the result values in upcoming resultset.
I have tried Both Ways :
Method 1:
var list1 = List1.GetList1();
var list2 = List2.GetList12();
List<ListViewModel> listViewmodelCollection = new List<ListViewModel>();
ListViewModel listViewmodelInstance = new ListViewModel();
foreach (var _list1 in list1)
{
listViewmodelInstance.LocationValues1 = _list1.LocationValues1;
listViewmodelInstance.LocationValues2 = _list1.LocationValues2;
foreach (var _list2 in list2)
{
listViewmodelInstance.LocationValues5 = _list2.LocationValues5;
listViewmodelInstance.LocationValues4 = _list2.LocationValues4;
listViewmodelInstance.RA = _list1.LocationValues1 + _list2.LocationValues4;
listViewmodelCollection.Add(listViewmodelInstance);
}
}
Method2:
List<ListViewModel> listViewmodelCollection = new List<ListViewModel>();
ListViewModel listViewmodelInstance = new ListViewModel();
var x = (from listobj in m.list
from n in m.list2
select new list4
{
LocationValues1 = listobj.LocationValues1,
LocationValues2 = n.LocationValues4,
LocationValues4 = listobj.LocationValues1 + n.LocationValues4
});
-- complete --
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace simple
{
class Program
{
public class List2
{
public string ContinentName { get; set; }
public decimal LocationValues4 { get; set; }
public decimal LocationValues5 { get; set; }
public Nullable<System.DateTimeOffset> CreatedDate { get; set; }
public static List<List2> GetList12()
{
var list2 = new List<List2>
{
new List2{ ContinentName="Asia",LocationValues4=399.23M,LocationValues5=22.90M },
new List2 { ContinentName ="Africa",LocationValues4=199.23M,LocationValues5=22.90M },
new List2 { ContinentName ="Australia",LocationValues4=199.23M,LocationValues5=22.90M },
new List2 { ContinentName ="Pakistan",LocationValues4=199.23M,LocationValues5=22.90M },
};
return list2;
}
}
public class List1
{
public string LocationName { get; set; }
public decimal LocationValues1 { get; set; }
public decimal LocationValues2 { get; set; }
public Nullable<System.DateTimeOffset> CreatedDate { get; set; }
public static List<List1> GetList1()
{
var list1 = new List<List1>
{
new List1 {LocationName="Africa",LocationValues1=199.23M,LocationValues2=22.90M },
new List1 {LocationName="Africa",LocationValues1=299.23M,LocationValues2=24.90M },
new List1 {LocationName="Africa",LocationValues1=399.23M,LocationValues2=25.90M },
new List1 {LocationName="Africa",LocationValues1=499.23M,LocationValues2=26.90M },
};
return list1;
}
}
public class ListViewModel
{
public string LocationName { get; set; }
public decimal LocationValues1 { get; set; }
public decimal LocationValues2 { get; set; }
public Nullable<System.DateTimeOffset> LocationCreatedDate { get; set; }
public decimal RA { get; set; }
public string ContinentName { get; set; }
public decimal LocationValues4 { get; set; }
public decimal LocationValues5 { get; set; }
public Nullable<System.DateTimeOffset> ContinentCreatedDate { get; set; }
}
static void Main(string[] args)
{
var list1 = List1.GetList1();
var list2 = List2.GetList12();
List<ListViewModel> listViewmodelCollection = new List<ListViewModel>();
ListViewModel listViewmodelInstance = new ListViewModel();
foreach (var _list1 in list1)
{
listViewmodelInstance.LocationValues1 = _list1.LocationValues1;
listViewmodelInstance.LocationValues2 = _list1.LocationValues2;
foreach (var _list2 in list2)
{
listViewmodelInstance.LocationValues5 = _list2.LocationValues5;
listViewmodelInstance.LocationValues4 = _list2.LocationValues4;
listViewmodelInstance.RA = _list1.LocationValues1 + _list2.LocationValues4;
listViewmodelCollection.Add(listViewmodelInstance);
}
}
}
Expected Output:
4 Rows
LocationName="Africa",LocationValues1=199.23M,LocationValues2=22.90M,ContinentName="Asia",LocationValues4=399.23M,LocationValues5=22.90M, RA=598.46
LocationName="Africa",LocationValues1=299.23M,LocationValues2=24.90M ,ContinentName ="Africa",LocationValues4=199.23M,LocationValues5=22.90M,RA=465.46
LocationName="Africa",LocationValues1=399.23M,LocationValues2=25.90M ContinentName ="Australia",LocationValues4=199.23M,LocationValues5=22.90M,RA=598.46
LocationName="Africa",LocationValues1=499.23M,LocationValues2=26.90M , ContinentName ="Pakistan",LocationValues4=199.23M,LocationValues5=22.90M.RA=698.46
But current output:
So, this seems messy at best. I'm not sure what your situation is but I would be very nervous about coding to merge 2 different data lists and expecting them to always be equal lengths etc..
I would strongly recommend that you add an interface to both lists so you could at least cast them to a base object and work with them that way instead.
That said I would try to select out the view model attributes via linq from the first set, then iterate through to add the data from the 2nd set and do the computations then.
Example:
var list1 = List1.GetList1();
var list2 = List2.GetList12();
List<ListViewModel> listViewmodelCollection = new List<ListViewModel>();
ListViewModel listViewmodelInstance = new ListViewModel();
listViewmodelCollection.AddRange(list1.Select(l => new ListViewModel()
{
LocationName = l.LocationName,
LocationCreatedDate = l.CreatedDate,
LocationValues1 = l.LocationValues1,
LocationValues2 = l.LocationValues2
}));
for (int i = 0; i < (listViewmodelCollection.Count - 1); i++)
{
var itm2 = list2.ElementAt(i);
if (itm2 != null)
{
listViewmodelCollection[i].ContinentName = itm2.ContinentName;
listViewmodelCollection[i].ContinentCreatedDate = itm2.CreatedDate;
listViewmodelCollection[i].LocationValues4 = itm2.LocationValues4;
listViewmodelCollection[i].LocationValues5 = itm2.LocationValues5;
listViewmodelCollection[i].RA = listViewmodelCollection[i].LocationValues1 + itm2.LocationValues4;
}
}
Given your classes this should get you to the output you wanted, at least for this narrow example.
You can use LINQ to combine the two Lists using the Zip extension method:
var listViewmodelCollection = list1.Zip(list2, (l1, l2) => new ListViewModel {
LocationName = l1.LocationName,
LocationValues1 = l1.LocationValues1,
LocationValues2 = l1.LocationValues2,
ContinentName = l2.ContinentName,
LocationValues4 = l2.LocationValues4,
LocationValues5 = l2.LocationValues5,
RA = l1.LocationValues1+l2.LocationValues4
}).ToList();

Unable to deserialize JSON array

Below is my class :
public class Employee : Base
{
public int Id { get; set; }
public string Fname { get; set; }
public DepartmentModel Department { get; set; }
}
public class DepartmentModel : Base
{
public int Id { get; set; }
public string DepartmentName { get; set; }
public List<Location> Locations { get; set; }
}
public class Locations
{
public string Area { get; set; }
public string StreetNo { get; set; }
public string Nearby { get; set; }
}
Response return from service:
var response = new
{
id = 100,
department = new
{
id = 200,
departmentName = "Abc",
locations = new[]
{
Employee.Department.Locations
.Select
(
lo => new
{
area = lo.Area,
streetNo = lo.streetNo,
nearby = lo.Nearby
}
).ToList()
}
}
};
return JsonConvert.SerializeObject(response);
Now when I try to deserialize this above JSON into my class Employee like below:
var deserialize = JsonConvert.DeserializeObject<Employee>(response.ToString());
Error:
How can I deserialize this above JSON?
The problem lies here:
locations = new[]
{
Employee.Department.Locations
.Select
(
lo => new
{
area = lo.Area,
streetNo = lo.streetNo,
nearby = lo.Nearby
}
).ToList()
}
The LINQ expression ends with .ToList() and thus is already returning a list of items. You are then wrapping that with new[] in an array. So, instead of being an array of Locations, the JSON is an array of an array of Locations.
Try removing the new[]. You don't want locations to be an array of lists
locations = Employee.Department.Locations
.Select(lo => new
{
area = lo.Area,
streetNo = lo.streetNo,
nearby = lo.Nearby
}
).ToList()
You need to instantiate a new Employee() and use the same casing as the classes:
var response = new Employee() // Instantiates Employee to ensure correct properties used.
{
Id = 100, // Has PascalCase.
Department = new DepartmentModel()
{
Id = 200,
DepartmentName = "Abc",
Locations = Employee.Department.Locations
.Select(lo => new Location
{
Area = lo.Area,
StreetNo = lo.StreetNo,
Nearby = lo.Nearby
}
).ToList()
}
};

Linq : Comparing 1 Child Collection to (Aggregated) ChildCollection(s)

I have a Linq question: (DotNet Framework 4.0)
I have the following classes:
public class Employee
{
public Guid? EmployeeUUID { get; set; }
public string SSN { get; set; }
}
public class JobTitle
{
public Guid? JobTitleSurrogateKey { get; set; }
public string JobTitleName { get; set; }
}
public class EmployeeToJobTitleMatchLink
{
public EmployeeToJobTitleMatchLink()
{
this.TheJobTitle = new JobTitle() { JobTitleSurrogateKey = Guid.NewGuid(), JobTitleName = "SomeJobTitle:" + Guid.NewGuid().ToString("N") };
}
public Guid LinkSurrogateKey { get; set; }
/* Related Objects */
public Employee TheEmployee { get; set; }
public JobTitle TheJobTitle { get; set; }
}
public class Organization
{
public Organization()
{
this.Links = new List<EmployeeToJobTitleMatchLink>();
}
public int OrganizationSurrogateKey { get; set; }
public ICollection<EmployeeToJobTitleMatchLink> Links { get; set; }
}
In my code below, I can compare 2 child-collections and get the results I need (in "matches1".
Here I am using the "SSN" string property to compare and find the overlaps. And the Console.Write for matches1 works as I expect.
What I don't know how to do is compare the first child collection (org10) to all the children in (allOtherOrgsExceptOrg10 (all the Organizations and all the Links of these Organizations )
The commented out code shows kinda what I'm trying to do, one of my many feeble attempts today.
But basically, match2 would be populated with all the SSN overlaps...but comparing org10 with allOtherOrgsExceptOrg10, all their "Links", and their Employee.SSN's.
org10 overlaps with org20 with "AAA", so match2 would contain "AAA". and org10 overlaps with org30 with "BBB" so match2 would contain "BBB".
Organization org10 = new Organization();
org10.OrganizationSurrogateKey = 10;
Employee e11 = new Employee() { SSN = "AAA", EmployeeUUID = new Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA") };
EmployeeToJobTitleMatchLink link11 = new EmployeeToJobTitleMatchLink();
link11.TheEmployee = e11;
org10.Links.Add(link11);
Employee e12 = new Employee() { SSN = "BBB", EmployeeUUID = new Guid("BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB") };
EmployeeToJobTitleMatchLink link12 = new EmployeeToJobTitleMatchLink();
link12.TheEmployee = e12;
org10.Links.Add(link12);
Organization org20 = new Organization();
org20.OrganizationSurrogateKey = 20;
Employee e21 = new Employee() { SSN = "AAA", EmployeeUUID = new Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA") };
EmployeeToJobTitleMatchLink link21 = new EmployeeToJobTitleMatchLink();
link21.TheEmployee = e21;
org20.Links.Add(link21);
Employee e22 = new Employee() { SSN = "CCC", EmployeeUUID = new Guid("CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC") };
EmployeeToJobTitleMatchLink link22 = new EmployeeToJobTitleMatchLink();
link22.TheEmployee = e22;
org20.Links.Add(link22);
Organization org30 = new Organization();
org30.OrganizationSurrogateKey = 30;
Employee e31 = new Employee() { SSN = "BBB", EmployeeUUID = new Guid("BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB") };
EmployeeToJobTitleMatchLink link31 = new EmployeeToJobTitleMatchLink();
link31.TheEmployee = e31;
org30.Links.Add(link31);
Employee e32 = new Employee();
e32.SSN = "ZZZ";
EmployeeToJobTitleMatchLink link32 = new EmployeeToJobTitleMatchLink();
link32.TheEmployee = e32;
org30.Links.Add(link32);
IList<Organization> allOtherOrgsExceptOrg10 = new List<Organization>();
/* Note, I did not add org10 here */
allOtherOrgsExceptOrg10.Add(org20);
allOtherOrgsExceptOrg10.Add(org30);
IEnumerable<EmployeeToJobTitleMatchLink> matches1 =
org10.Links.Where(org10Link => org20.Links.Any(org20Link => org20Link.TheEmployee.SSN.Equals(org10Link.TheEmployee.SSN, StringComparison.OrdinalIgnoreCase)));
IEnumerable<EmployeeToJobTitleMatchLink> matches2 = null;
//org10.Links.Where(org10Link => ( allOtherOrgs.Where ( anyOtherOrg => anyOtherOrg.Links.Any(dbSideChild => dbSideChild.TheEmployee.SSN == org10Link.TheEmployee.SSN)) );
if (null != matches1)
{
foreach (EmployeeToJobTitleMatchLink link in matches1)
{
Console.WriteLine(string.Format("matches1, SSN = {0}", link.TheEmployee.SSN));
}
}
if (null != matches2)
{
foreach (EmployeeToJobTitleMatchLink link in matches2)
{
Console.WriteLine(string.Format("matches2, SSN = {0}", link.TheEmployee.SSN));
}
}
matches2 =
allOtherOrgsExceptOrg10.SelectMany(x => x.Links)
.Where(x => org10.Links.Select(o => o.TheEmployee.SSN).Contains(x.TheEmployee.SSN));
You can use the SelectMany on the allOther collection to select all Links over all org's. Then check if any SSN is inside the org10 List.
See: http://msdn.microsoft.com/en-us/library/system.linq.enumerable.selectmany(v=vs.100).aspx
You can use SelectMany to flatten out the collection and then use it just like you have for matches1
IEnumerable<EmployeeToJobTitleMatchLink> matches2 =
org10.Links.Where(
org10Link =>
allOtherOrgsExceptOrg10.SelectMany(allOtherOrgs => allOtherOrgs.Links).Any(
anyOtherLink =>
anyOtherLink.TheEmployee.SSN.Equals(org10Link.TheEmployee.SSN, StringComparison.OrdinalIgnoreCase)));
The SelectMany will make it seem like one IEnumerable instead of and IEnumerable of an IEnumerable.

Hierarchical List Conversion For Tree View

I have a list of records that I want to display in a tree view, it has a structure like this.
public class Account
{
public string ac_cd { get; set; }
public string ac_name { get; set; }
public string ac_parent_cd { get; set; }
public string ac_nature { get; set; }
}
I want to convert this into a hierarchical structure, so assuming I have a list that contains the following items,
ac_cd = "01", ac_name = "Cash", ac_parent_cd = "Null", ac_nature = "Asset",
ac_cd = "02", ac_name = "Supplies", ac_parent_cd = "Null", ac_nature = "Asset",
ac_cd = "01.01", ac_name = "ACME Corp Cash", ac_parent_cd = "01", ac_nature = "Asset",
ac_cd = "02.01", ac_name = "ACME Corp Supplies", ac_parent_cd = "02", ac_nature = "Expense",
ac_cd = "02.01.01", ac_name = "ACME Corp Office Supplies", ac_parent_cd = "02.01", ac_nature = "Expense",
I want to convert these items into a hierarchical list like this,
01-Cash
---01.01-ACME Corp Cash
02-Supplies
---02.01-ACME Corp Supplies
------02.01.01-ACME Corp Office Supplies
There can be many number of levels for an account. My code so far can only make a child account up to a single level. Here is the POCO of the hierarchical model.
public class AccountTree
{
public string ac_info { get; set; }
public List<ChildAccount> ac_child { get; set; }
}
public class ChildAccount
{
public string ac_info { get; set; }
}
And here is my code.
List<Account> accountList = new List<Account>();
accountList.Add(new Account { ac_cd = "01", ac_name = "Cash", ac_parent_cd = "", ac_nature = "Asset" });
accountList.Add(new Account { ac_cd = "01.01", ac_name = "Abc Cash", ac_parent_cd = "01", ac_nature = "Asset" });
accountList.Add(new Account { ac_cd = "01.02", ac_name = "Xyz Cash", ac_parent_cd = "01", ac_nature = "Asset" });
List<AccountTree> targetAccountList = new List<AccountTree>();
List<ChildAccount> childAccountList = new List<ChildAccount>();
foreach (var childAccountGrouping in accountList.GroupBy(o => new { o.ac_parent_cd }))
{
if (childAccountGrouping.Key.ac_parent_cd == "")
{
continue;
}
var childAccounts = childAccountGrouping.ToList();
foreach (var childAccount in childAccounts)
{
childAccountList.Add(new ChildAccount { ac_info = childAccount.ac_cd + childAccount.ac_name + childAccount.ac_nature });
}
var parentAccount = (from p in accountList
where p.ac_cd == childAccountGrouping.Key.ac_parent_cd
select p).Single();
AccountTree accountTree = new AccountTree
{
ac_info = parentAccount.ac_cd + parentAccount.ac_name + parentAccount.ac_nature,
ac_child = childAccountList
};
targetAccountList.Add(accountTree);
}
I'm pretty sure I'll have to change this significantly. Would appreciate any assistance.
I would just change the Account class like that:
public class Account
{
public string ac_cd { get; set; }
public string ac_name { get; set; }
public Account ac_parent_cd { get; set; }
public List<Account> ac_children_cd { get; set; }
public string ac_nature { get; set; }
}
now you have easy access to parent and children of all elements

Categories

Resources