I want to to display two tables information at a time.
List<int> order_track = db.Order_Trackings.Where(e => e.UID == id).Select(q => q.ID).ToList();
if (order_track == null)
{
var rate = db.Ratings.OrderByDescending(e => e.Rate).Take(5);
}
List<int> fidList = db.OrderFoods.Where(q => order_track.Contains(q.OID)).Select(q => q.FID).ToList();
var qs = (from x in fidList
group x by x into g
let count = g.Count()
orderby count descending
select new { KEY = g.Key });
if (order_track.Count == 2)
{
var one = qs;
List<int> idList = new List<int>();
foreach (var val in one)
{
idList.Add(val.KEY);
}
var food = db.Foods.Where(q => idList.Contains(q.ID));
var rate = db.Ratings.OrderByDescending(e => e.Rate).FirstorDefault();
return Request.CreateResponse(HttpStatusCode.OK, rate);
I want to do something like this I hope you will understand what i am trying to achieve Thanks in advance.
var food = db.Foods.Where(q => idList.Contains(q.ID)&&db.Ratings.OrderByDescending(e => e.Rate).FirstorDefault());
return Request.CreateResponse(HttpStatusCode.OK, rate);
If you want to combine the two results into one variable, then the easiest way to do so is by creating an anonymous object, like this:
var result = new
{
food = db.Foods.Where(q => idList.Contains(q.ID)),
rate = db.Ratings.OrderByDescending(e => e.Rate).FirstorDefault()
};
return Request.CreateResponse(HttpStatusCode.OK, result);
You could also create a class with two properties and then create an instance of that class, but if this is the only place where you would use that class then I wouldn't bother doing that.
Related
I have posted this earlier but the objective of what I am trying to achieve seems to have lost hence re-posting it to get explain myself better.
I have a collection that has duplicate productnames with different values. My aim is to get a list that would sum these productnames so that the list contains single record of these duplicates.
For e.g
If the list contains
Product A 100
Product A 200
The result object should contain
Product A 300
So as you can see in my code below, I am passing IEnumerable allocationsGrouped to the method. I am grouping by productname and summing the Emv fields and then looping it so that I created a new list of the type List and pass it to the caller method. The problem what I seeing here is on the following line of code Items = group. Items now contains original list without the sum. Hence the inner foreach loop runs more than ones because there are duplicates which defeats my purpose. I finally need to return result object that has non duplicate values which are summed based on the above criteria. Could you please tell me where I am going wrong.
private static List<FirmWideAllocationsViewModel> CreateHierarchy(string manStratName, IEnumerable<FIRMWIDE_MANAGER_ALLOCATION> allocationsGrouped, List<FirmWideAllocationsViewModel> result)
{
var a = allocationsGrouped
.Where(product => !string.IsNullOrEmpty(product.PRODUCT_NAME))
.GroupBy(product => product.PRODUCT_NAME)
.Select(group => new
{
ProductName = group.Key, // this is the value you grouped on - the ProductName
EmvSum = group.Sum(x => x.EMV),
Items = group
});
var b = a;
var item = new FirmWideAllocationsViewModel();
item.Hierarchy = new List<string>();
item.Hierarchy.Add(manStratName);
result.Add(item);
foreach (var ac in b)
{
var productName = ac.ProductName;
var emvSum = ac.EmvSum;
foreach (var elem in ac.Items)
{
var item2 = new FirmWideAllocationsViewModel();
item2.Hierarchy = new List<string>();
item2.Hierarchy.Add(manStratName);
item2.Hierarchy.Add(elem.PRODUCT_NAME);
item2.FirmID = elem.FIRM_ID;
item2.FirmName = elem.FIRM_NAME;
item2.ManagerStrategyID = elem.MANAGER_STRATEGY_ID;
item2.ManagerStrategyName = elem.MANAGER_STRATEGY_NAME;
item2.ManagerAccountClassID = elem.MANAGER_ACCOUNTING_CLASS_ID;
item2.ManagerAccountingClassName = elem.MANAGER_ACCOUNTING_CLASS_NAME;
item2.ManagerFundID = elem.MANAGER_FUND_ID;
item2.ManagerFundName = elem.MANAGER_FUND_NAME;
item2.Nav = elem.NAV;
item2.EvalDate = elem.EVAL_DATE.HasValue ? elem.EVAL_DATE.Value.ToString("MMM dd, yyyy") : string.Empty;
item2.ProductID = elem.PRODUCT_ID;
item2.ProductName = elem.PRODUCT_NAME;
item2.UsdEmv = Math.Round((decimal)elem.UsdEmv);
item2.GroupPercent = elem.GroupPercent;
item2.WeightWithEq = elem.WEIGHT_WITH_EQ;
result.Add(item2);
}
}
return result;
}
change it to:
var result = allocationsGrouped
.Where(product => !string.IsNullOrEmpty(product.PRODUCT_NAME))
.GroupBy(product => product.PRODUCT_NAME)
.Select(group => {
var product = group.First();
return new FirmWideAllocationsViewModel()
{
Hierarchy = new List<string>() { manStratName, product.PRODUCT_NAME },
FirmID = product.FIRM_ID,
FirmName = product.Item.FIRM_NAME,
ManagerStrategyID = product.MANAGER_STRATEGY_ID,
ManagerStrategyName = product.MANAGER_STRATEGY_NAME,
ManagerAccountClassID = product.MANAGER_ACCOUNTING_CLASS_ID,
ManagerAccountingClassName = product.MANAGER_ACCOUNTING_CLASS_NAME,
ManagerFundID = product.MANAGER_FUND_ID,
ManagerFundName = product.MANAGER_FUND_NAME,
Nav = product.NAV,
EvalDate = product.EVAL_DATE.HasValue ? product.EVAL_DATE.Value.ToString("MMM dd, yyyy") : string.Empty,
ProductID = product.PRODUCT_ID,
ProductName = product.PRODUCT_NAME,
UsdEmv = Math.Round((decimal)product.UsdEmv),
GroupPercent = product.GroupPercent,
WeightWithEq = product.WEIGHT_WITH_EQ,
//assign aggregate Sum here
EmvSum = group.Sum(x => x.EMV),
};
});
I have a list of complex objects i.e.
class MyObject
{
public bool selected;
public int id;
public string name;
}
List<MyObject> theObjects = functionThatSelectsObjectsFromContainer();
And I have a list from another source that just give me int ids that are in the list of objects
List<int> idList = functionThatReturnsListOfIds();
Now for each of the items in the idList I want to set the selected property true. I know I can set up a foreach of one list and then search for the matching items in the other list and set it that way, but I was wondering if there's a different way that might be quicker.
Conclusion
I did some testing on all my methods below, as well as un-lucky's answer, and the fastest of them all was option 2 below, ie
var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();
results.ForEach(o => o.selected = true);
Another way of doing it with Linq, where we iterate around theObjects and check each one to see if its' id exists in idList:
1
var result = theObjects.ForEach(o => o.selected = idList.Contains(o.id) ? true : false);
or using Join and ForEach, where we first extract the matching items using Join and then iterate around those items:
2
var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();
results.ForEach(o => o.selected = true);
or, you can use Select with ForEach and FirstOrDefault. This is probably going to be slower than the other 2:
3
theObjects
.Select(o => o.id)
.Where(i => idList.Contains(i)).ToList()
.ForEach(i =>
theObjects.FirstOrDefault(o => o.id == i).selected = true);
I did some testing on the 3 methods I posted, where we have 10000 MyObjects and 1000 unique ids. I ran each method 1000 times, and then got the mean ElapsedMillliseconds for each.
The results were
1
8.288 ms
2
0.19 ms
3
57.342 ms
one = 0;
two = 0;
three = 0;
for (var i = 0; i <1000; i++) {
RunTest();
}
oneMean = one / 1000;
twoMean = two / 1000;
threeMean = three / 1000;
where
private void RunTest()
{
ResetData();
var stopwatch = Stopwatch.StartNew();
theObjects.ForEach(o => o.selected = idList.Contains(o.id) ? true : false);
stopwatch.Stop();
one += stopwatch.ElapsedMilliseconds;
ResetData();
stopwatch = Stopwatch.StartNew();
var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();
results.ForEach(o => o.selected = true);
stopwatch.Stop();
two += stopwatch.ElapsedMilliseconds;
ResetData();
stopwatch = Stopwatch.StartNew();
theObjects
.Select(o => o.id)
.Where(i => idList.Contains(i)).ToList()
.ForEach(i =>
theObjects.FirstOrDefault(o => o.id == i).selected = true);
stopwatch.Stop();
three += stopwatch.ElapsedMilliseconds;
}
private void ResetData()
{
theObjects = new List<MyObject>();
idList = new List<int>();
var rnd = new Random();
for (var i=0; i<10000; i++) {
theObjects.Add(new MyObject(){id = i});
}
for (var i=0; i<=1000; i++) {
var r = rnd.Next(0, 1000);
while (idList.Contains(r)) {
r = rnd.Next(0, 10000);
}
idList.Add(r);
}
}
I tested un-lucky's answer (most upvotes right now) and it got a mean score of 147.676
foreach(var obj in theObjects.Where(o => idList.Any(i=> i == o.id)))
{
obj.selected = true;
}
I think you can do something like this, to make that working
foreach(var obj in theObjects.Where(o => idList.Any(i=> i == o.id)))
{
obj.selected = true;
}
With the help of Linq, you can use Where, ToList and ForEach to achieve your required behaviour -
theObjects.Where(x => idList.Contains(x.id)).ToList().ForEach(y => y.selected = true);
Using linq you can do like so
theObjects.Where(g => idList.Contains(g.id)).ForEach(g => g.selected = true);
You can try below solution where you don't need to use Where and Contains:
theObjects.ForEach(a => a.selected = idList.Exists(b => a.id == b));
New to C# and appreciate any help. The issue is that I need to filter the results of my api call against an array (using an "allowedA" and "allowedB" array.) I don't know how to edit the lambda expression to check against the loop.
var activities = await _restClientTaxonomy.GetTaxonomyFullAsync(TAXONOMY_CLASSIFICATIONID_FOR_ACTIVITY);
var activityTypes = await _restClientTaxonomy.GetTaxonomyFullAsync(TAXONOMY_CLASSIFICATIONID_FOR_ACTIVITY_TYPES);
var documentEventxx = activities.Select(type => type.Id);
long [] allowedA = new long []{ 7137, 40385637};
long [] allowedB = new long []{ 7137, 40385637};
foreach (long value in documentEventxx)
{
foreach (var item in allowed)
{
if (item == value) {
//These are the values I am looking for -> values that are part of the documentEventxx and allowedB.
}
}
}
var result = activityTypes.Select(type => new CategoryViewModel
{
Id = type.Id,//This is where I want to add only items that are in the allowedA array
Text = type.Name,
Types = activities.Where(a => a.ParentId == type.Id).Select(t => new TaxonomyMemberTextItem
{
Id = t.Id, //This is where I want to add only items that are in the allowedB array
Text = t.Name
}).ToList()
}).ToArray();
I have been reading about lambda expressions and foreach loops so please don't just post a random link.
Thanks in advance.
Filter the values before Selecting.
activityTypes.Where(x=>allowedA.Contains(x.Id)).Select(type => new CategoryViewModel
{
Id = type.Id,
Text = type.Name,
Types = activities.Where(a => a.ParentId == type.Id && allowedB.Contains(a.Id)).Select(t => new TaxonomyMemberTextItem
{
Id = t.Id,
Text = t.Name
}).ToList()
})
To filter you use .Where. You .Select to create a list of new types. So in order to filter, then create the lists of objects you want:
var result = activityTypes.Where(type=>isAllowed(type.Id)).Select(type => new CategoryViewModel
{
Id = type.Id,//This is where I want to add only items that are in the allowedA array
Text = type.Name,
Types = activities.Where(a => a.ParentId == type.Id&&isAllowed(a.Id)).Select(t => new TaxonomyMemberTextItem
{
Id = t.Id, //This is where I want to add only items that are in the allowedB array
Text = t.Name
}).ToList()
}).ToArray();
I need to return two fields using a lambda expression. The first one is the sum of the amount field and the second one is CurrentFinancial year. Below is the code that I have written, how do I include CurrentFinancialYear?
var amount = dealingContext.vw_GetContribution
.Where(o => o.ContactID == contactId)
.Sum(o => o.Amount);
return new Contribution { Amount = amount ?? 0, CurrentFinancialYear = };
Grouping by Year should do the trick:
from entry in ledger.Entries
where entry.ContactID == contactId
&& entry.Time.Year == currentFinancialYear
group entry by entry.Time.Year
into g
select new Contribution ()
{
Amount = g.ToList ().Sum (e => e.Amount),
CurrentFinancialYear = g.Key
};
UPDATE - just return the first/default result...
(from entry in ledger.Entries
where entry.ContactID == contactId
&& entry.Time.Year == currentFinancialYear
group entry by entry.Time.Year
into g
select new Contribution ()
{
Amount = g.ToList ().Sum (e => e.Amount),
CurrentFinancialYear = g.Key
}).FirstOrDefault();
First of all use a simple select
var contribution = dealingContext.vw_GetContribution
.Where(o => o.ContactID == contactId).ToList();
It will give you a list of type vw_GetContribution
Then use groupby on this list as
var groupedContribution = contribution.GroupBy(b => b.CurrentFinancialYear).ToList();
Now you can iterate through or use this list as
foreach(var obj in groupedContribution.SelectMany(result => result).ToList())
{
var amount = obj.Amount;
var Year = obj.CurrentFinancialYear;
}
OR
In single line, you can do all the above as
var contList = context.vw_GetContribution
.Select(a => new { a.Amount, a.CurrentFinancialYear })
.GroupBy(b => b.CurrentFinancialYear)
.SelectMany(result => result).ToList();
I hope this will solve your problem.
Can you try this:
var amount = dealingContext.vw_GetContribution
.Where(o => o.ContactID == contactId)
.GroupBy(o=> new { o.CurrentFinancialYear, o.Amount})
.Select(group =>
new {
year= group.Key.CurrentFinancialYear,
sum= group.Sum(x=>x.Amount)
});
var list = new List<ListCreaditInBankView>();
var banktemp = m_banksRepository.Banks;
foreach (Bank bank in banktemp)
{
var bankbranchtemp = m_banksRepository.BankBranches.Where(x => x.BankId == bank.Id);
foreach (BankBranch bankBranch in bankbranchtemp)
{
var creditortemp = m_creditorsRepository.Creditors.Where(x => x.BankBranchId == bankBranch.Id);
list.Add(new ListCreaditInBankView(){Bank = bank, Creditors = creditortemp});
}
}
I need get List<ListCreaditInBankView> without these cycles.
I tried, but it only gets a Creditors
var lists = (from bank in banksTemp
let creditorBank = m_creditorsRepository.GetCreditorBank(bank.BankBranches.Select(x => x.Id).ToList())
select new ListCreaditInBankView() {Bank = bank, Creditors = creditorBank}).ToList();
Try the following:
var lists = (from bank in m_banksRepository.Banks
select new ListCreaditInBankView
{
Bank = bank,
Creditors = creditorsRepository.GetCreditorBank(bank.BankBranches
.Select(x => x.Id).ToList())
}).ToList();
Or if you prefer the other style LINQ (method chaining it's called, thanks Numan :)):
var lists = m_banksRepository.Banks
.Select(bank => new ListCreaditInBankView
{
Bank = bank,
Creditors = creditorsRepository.GetCreditorBank(bank.BankBranches
.Select(x => x.Id).ToList())
}).ToList();
If you're using Linq 2 Entity framework, there's another approach you can try.
http://msdn.microsoft.com/en-us/library/bb896272.aspx
You just need to be sure, that you've set your tables and keys in your database correctly (or at least mapping in the generated model), otherwise it won't work.