So i have following two list using linq.
List<One> one= A.Common
.Join(B.Common,
a => a.ID,
b=> b.ID,
(a, b) => new One
{
ID = b.PID,
Name = b.PCName,
LastName = a.LName
}).ToList();
List<One> two = (from c in D.Options
select new One
{
MainName = c.mName
}).ToList();
List<One> sn = one.Concat(two).ToList();
I am concating both list. But when i debug i am getting MainName as null in sn list.
How do i get data from both list in single list??
This is how you do it:
var sn = one.Zip(two, (x, y) => new One{
ID = x.ID,
Name = x.Name,
LastName = x.LastName,
MainName = y.MainName
});
You want the MainName property assigned for all the list values in List ONE ?
As from above code concatenation will join two list and the MainName will be not set for list one elements.
one.Concat(two)
Above line will just concat the both lists to one list elements.
You can use the LINQ Concat and ToList methods:
var mergedList = YourFirstList.Concat(YourSecondList)
.Concat(YourThirdList)
.ToList();
Edit:
one.Concat(two).Select(g => g.Aggregate((p1,p2) => new One
{
ID = p1.ID,
Name = p1.PCName,
LastName = p1.LName,
MainName = p2.mName
}));
more efficient ways to do this - the above will basically loop through all the entries, creating a dynamically sized buffer.
var mergedList = new List<One>(YourFirstList.Count +
YourSecondList.Count +
YourThirdList.Count);
mergedList.AddRange(YourFirstList);
mergedList.AddRange(YourSecondList);
mergedList.AddRange(YourThirdList);
AddRange is special-cased for ICollection<T> for efficiency.
You can use the Zip method.
one.Zip(two,(o1, o2) => new One()
{
ID = o1.ID,
Name = o1.PCName,
LastName = o1.LName,
MainName = o2.mName
});
Related
I am selecting data from a data store
I am able to fetch first array [0] {IHSWCFService.ServiceReference1.Observation} using below query
var newData = data.Select(a => new IHSData
{
PriceSymbol = Convert.ToString(a.PriceId),
PeriodData = Convert.ToDateTime(a.ObservationVector.Select(x => x.Period).FirstOrDefault()),
StatusID = Convert.ToInt32(a.ObservationVector.Select(x => x.StatusId).ToList()),
Price = Convert.ToDouble(a.ObservationVector.Select(x => x.price).FirstOrDefault()),
});
But I want to select next array also. as showing in below screen screenshot
[0]{IHSWCFService.ServiceReference1.Observation}
[1]{IHSWCFService.ServiceReference1.Observation}
[2]{IHSWCFService.ServiceReference1.Observation}
Could you please help me. Thanks
You might want all your properties in IHSData to be lists:
var newData = data.Select(a => new IHSData
{
PriceSymbol = Convert.ToString(a.PriceId),
PeriodData = a.ObservationVector.Select(x => Convert.ToDateTime(x.Period)).ToList(),
StatusID = a.ObservationVector.Select(x => Convert.ToInt32(x.StatusId)).ToList(),
Price = a.ObservationVector.Select(x => Convert.ToDouble(x.price)).ToList(),
});
Which is not such a good idea, because you have to index them separately. So another option would be to use SelectMany:
var newData = data
.SelectMany(a => a.ObservationVector.Select(v =>
new IHSData
{
PriceSymbol = Convert.ToString(a.PriceId), // parent PriceId
PeriodData = Convert.ToDateTime(v.Period),
StatusID = Convert.ToInt32(v.StatusId),
Price = Convert.ToDouble(v.price),
}))
.ToList();
The latter approach will create a separate IHSData instance for each ObservationVector, and some of them will share the same PriceId of the parent class.
Or, the third approach would be to have a new class, which would be the "parsed version of the ObservationVector", i.e. contain properties for parsed values, something like:
var newData = data.Select(a => new IHSData
{
PriceSymbol = Convert.ToString(a.PriceId),
Data = a.ObservationVector.Select(x => ConvertObservationVector(x)).ToList()
});
where ConvertObservationVector is a method which converts from an ObservationVector to your parsed class.
I have two lists of same type with different key value pairs,
List1 has "isPermanent = true" and List2 has false value and also
List1 has an extra key "nextVacationDate".
Im trying to do union of these as below but im afraid I will still get the duplicates because of different values. I need to merge both lists in to one list and order by List1 first (Permanent employees first)..is there a better way to do this using LINQ?
public newList1 List1(string abcd)
{
var result = serviceMethod1(abcd);
var newList1 = new List<emp>();
if (result == null) return null;
newList.AddRange(
result.Select(x => new Model
{
firstName = x.FName,
secondName = x.SName,
address = x.Address,
employeeId = x.EmpId,
isPermanent = true,
nextVacationDate =x.VacDt,
salary = x.Bsalary
}));
return newList1;
}
public newList2 List2(string defg)
{
var result = serviceMethod2(defg);
var newList2 = new List<emp>();
if (result == null) return null;
newList.AddRange(
result.Select(x => new Model
{
firstName = x.FName,
secondName = x.SName,
address = x.Address,
employeeId = x.EmpId,
isPermanent = false,
salary = x.Bsalary
}));
return newList2;
}
private List<emp> EmployyeList(List<emp> newList1, List<emp> newList2)
{
var sortedEmpList1 = newList1.OrderBy(i => i.Fname);
var sortedEmpList2 = newList2.OrderBy(i => i.Fname);
List<MeterModel> combinedList = newList1.Union(newList2) as List<emp>;
return combinedList;
}
You can filter the 2nd list to avoid duplicates:
newList1.Union(newList2.Where(emp2 => !newList1.Any(emp1 => emp1.employeeId == emp2.employeeId)))
I have a list with 3 entries -
public class entry
{
string name;
string age;
string likes;
}
List<entry> groupEntry = new List<entry>();
Where -
groupEntry[0].name = "john";
groupEntry[0].age= "26";
groupEntry[0].likes= "cats";
groupEntry[1].name = "john";
groupEntry[1].age= "26";
groupEntry[1].likes= "dogs";
groupEntry[2].name = "matt";
groupEntry[2].age= "32";
groupEntry[2].likes= "frogs";
What i am trying to do is make a new list, whereby name is a unique identifier, and just create one entry per name however add the likes together into on string array with the resulting list looking like -
public class filteredEntry
{
string name;
string age;
List<string> likes;
}
List<filteredEntry> filteredGroupEntry = new List<filteredEntry>();
filteredGroupEntry [0].name = "john";
filteredGroupEntry [0].age= "26";
filteredGroupEntry [0].likes= ["cats", "dogs"];
filteredGroupEntry [1].name = "matt";
filteredGroupEntry [1].age= "32";
filteredGroupEntry [1].likes= "frogs";
My thoughts were to do a foreach with groupEntry and each time entry[i].name changes make a new record in filteredGroupEntry however could not get this to work with a new array for likes. How can I achieve this?
First of all, you need to make the fields in your entry class public. Until now your code won't compile.
Second is that likes is already a string so you cannot transform it into an array, but what you could do is just to concatenate all the stuff that a person likes and separate them with a ,. So you would group by name and take all likes values in one string. This code takes only the first age value (assuming that it is always the same John with the same age May be not the smartest solution.
List<entry> filteredList = groupEntry.GroupBy(x => x.name)
.Select(x => new entry
{
name = x.First().name,
age = x.First().age,
likes = String.Join(", ", x.Select(l=>l.likes))
}).ToList();
Later on when you want to separate the like thingies again you could split by , like this:
string [] allOneLikes = filteredList[0].likes.Split(',');
EDIT:
I just saw that you edited your post and added the filteredEntry class.
This changes the situation of course. So you could then use this class in the Select statement:
List<filteredEntry> filteredList = groupEntry.GroupBy(x => x.name)
.Select(x => new filteredEntry
{
name = x.First().name,
age = x.First().age,
likes = x.Select(l=>l.likes).ToList()
}).ToList();
I suggest grouping by via Linq:
List<filteredEntry> filteredGroupEntry = groupEntry
.GroupBy(entry => new { // grouping by name + age
name = entry.name,
age = entry.age})
.Select(chunk => new filteredEntry() {
name = chunk.Key.name,
age = chunk.Key.age,
// collapse all likes into list
likes = chunk.Select(entry => entry.likes).ToList()})
.ToList();
I am using LINQ to entitiy in my project.
I have this LINQ:
var result = (from inspArch in inspectionArchives
from inspAuth in inspArch.InspectionAuthority
select new
{
Id = inspArch.Id,
clientId = inspArch.CustomerId,
authId = inspAuth.Id
}).ToList();
After LINQ is executed result has this value :
Is there any elegant way (for example using LINQ or change above existing LINQ) to create from the list above, new list like that:
I haven't built this to see if it compiles, but this should work. You need to aggregate the Id and AuthId fields.
var result = (from inspArch in inspectionArchives
from inspAuth in inspArch.InspectionAuthority
select new
{
Id = inspArch.Id,
clientId = inspArch.CustomerId,
authId = inspAuth.Id
})
.GroupBy(g => g.clientId)
.select(s => new {
Id = string.Join(",", s.Select(ss => ss.Id.ToString())),
ClientId = s.Key,
AuthId = string.Join(",", s.Select(ss => ss.authId.ToString()).Distinct()),
}).ToList();
You need group by and you can apply String.Join on the resulting IGrouping:-
var result = (from inspArch in inspectionArchives
from inspAuth in inspArch.InspectionAuthority
group new { inspArch, inspAuth } by inspArch.CustomerId into g
select new
{
Id = String.Join(",",g.Select(x => x.inspArch.Id),
clientId = x.Key,
authId = String.Join(",",g.Select(x => x.inspAuth.Id)
}).ToList();
The tricky part here is to group both objects i.e. new { inspArch, inspAuth } because we need to access properties from both.
Update:
Since this is entity framework, it won't be able to translate the method String.Join to SQL, so we can bring back the grouped object to memory using AsEnumerable and then project it like this:-
var result = (from inspArch in inspectionArchives
from inspAuth in inspArch.InspectionAuthority
group new { inspArch, inspAuth } by inspArch.CustomerId into g
select g).AsEnumerable()
.Select(g => new
{
Id = String.Join(",",g.Select(x => x.inspArch.Id),
clientId = x.Key,
authId = String.Join(",",g.Select(x => x.inspAuth.Id)
}).ToList();
I have a linq query which is working fine.How can i use group by in this query.I need to group by username and itemid and i should get sum(Amount)(All are in table called Carts)
FoodContext db = new FoodContext();
List<CartListing> fd = (from e in db.FoodItems
join o in db.Carts on e.itemid equals o.itemid
where e.itemid == o.itemid
select new CartListing
{
Itemname =e.itemname,
Amount =o.amount,
Price=(float)(e.price*o.amount),
}).ToList();
CartModel vm = new CartModel { CartListings = fd };
I can't see username anywhere in your code example, but to group by Itemname and sum Amount, you would something like:
var grouped = fd.GroupBy(
cl => cl.Itemname,
(key, group) => new CartListing
{
Itemname = key,
Amount = group.Sum(cl => cl.Amount),
Price = group.Sum(cl => cl.Price)
});
To also group by username, just generate a text key containing both values, for instance delimited by a character you know will be contained in neither.
Use:
var grouped = fd.GroupBy((a => new { a.itemid,a.name }) into grp
select new MyClass
{
MyProperty1=grp.key.itemid,
MyProperty2 =grp.Sum(x=>x.whatever)
}
Public MyClass
{
public string MyProperty1 {get;set;}
public int MyProperty2 {get;set;}
}
This way it won't be anonymous