C# LINQ, need help about logic / algorithm - c#

I have a list of values, as below , the number at left side represents the object to be removed / inserted, where the "insert/remove" is action taken
1 insert
2 insert
3 insert
2 remove
4 insert
2 insert
3 remove
5 insert
3 insert
5 remove
And final result i want is "5 remove".
So if the position of removed object in list is bigger than position of same object from insert, then it will be removed, others will leave intact(1,2,3,4 will be inserted). can we do it with LINQ?

Let's say you have class Operation with 2 properties ID and CRUD
public class Operation
{
public int ID { get; set; }
public string CRUD { get; set; }
}
var result = list.GroupBy(x => x.ID)
.ToDictionary(x => x.Key, x => x.Last().CRUD);
//if you want to have same List<Operation>
list = list.GroupBy(x => x.ID)
.Select(x=> new Operation { ID = x.Key, CRUD = x.Last().CRUD }).ToList();
Here dotNetFiddle
EDIT:
public static void Main()
{
List<Operation> list = new List<Operation>();
Operation o1 = new Operation();
o1.ID = 1;
o1.CRUD = "Insert";
list.Add(o1);
Operation o2 = new Operation();
o2.ID = 2;
o2.CRUD = "Insert";
list.Add(o2);
Operation o3 = new Operation();
o3.ID = 3;
o3.CRUD = "Insert";
list.Add(o3);
Operation o4 = new Operation();
o4.ID = 2;
o4.CRUD = "Remove";
list.Add(o4);
Operation o5 = new Operation();
o5.ID = 4;
o5.CRUD = "Insert";
list.Add(o5);
Operation o6 = new Operation(){ID=2, CRUD = "Insert"};
list.Add(o6);
Operation o7= new Operation(){ID=3, CRUD = "Remove"};
list.Add(o7);
Operation o8= new Operation(){ID=5, CRUD = "Insert"};
list.Add(o8);
Operation o9= new Operation(){ID=3, CRUD = "Insert"};
list.Add(o9);
Operation o10= new Operation(){ID=5, CRUD = "Remove"};
list.Add(o10);
var result = list.GroupBy(x => x.ID).ToDictionary(x => x.Key, x => x.Last().CRUD);
foreach(var item in result)
{
Console.WriteLine(item.Key + ": " + item.Value);
}
list = list.GroupBy(x => x.ID)
.Select(x=> new Operation { ID = x.Key, CRUD = x.Last().CRUD }).ToList();
Console.WriteLine("List values");
foreach(var item in list)
{
Console.WriteLine(item.ID + ": " + item.CRUD);
}
//output for 5 is Remove.
}
public class Operation
{
public int ID { get; set; }
public string CRUD { get; set; }
}

Not sure to understand the question but yoiu can check if the higgest ID is equal to "remove", like that :
public class MyList
{
public int Id { get; set; }
public string ToDo { get; set; }
}
List<MyList> MyList = new List<MyList>();
if ( MyList.OrderBy(c => c.Id).LastOrDefault().ToDo == "remove")
{
// Code to remove what need to be removed
}

Related

changing the sorted column value change the sorting list , while wants to use the ThenByDescending on first ordered list

I have following code, In which there are list of students , and I want to sort the students first by value column which contains decimal values and after that I want to sort the already sorted list with same column but with different values . Just for understanding , I changed values using foreach loop in the below example.
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var students = new List<Student>()
{
new Student() { StudentId=1,Name = "Alice", Appd = 10, Value = 3.5 },
new Student() { StudentId=2,Name = "Bob", Appd = 10, Value = 3.7 },
new Student() { StudentId=3,Name = "Raul", Appd = 10, Value = 0.1 },
new Student() { StudentId=4,Name = "Charlie", Appd = 0, Value = 3.6 },
new Student() { StudentId=5,Name = "Dave", Appd = 0, Value = 3.9 },
new Student() { StudentId=6,Name = "Emma", Appd = 0, Value = 3.8 }
};
var orderedFields = students.OrderByDescending(x => x.Value);//5,6,2,4,1,3
foreach ( Student s in orderedFields )
{
s.Value = 120;
}
orderedFields = orderedFields.ThenByDescending(x => x.Value);
var newlist1 = orderedFields.Select(X => X.StudentId).ToList();
}
}
public class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
public int Appd { get; set; }
public double Value { get; set; }
}
}
but as soon I change the Value column values it start to change the order of items in list , and if I take this in another list then I will be not able to use the ThenByDescending feature results.
This is sample code to simplify the problem , in real example these columns name come from Database and based on those columns I want to sort the list, first by first column and then by another columns mentioned. For example in MySQL it will be something like this order by col1 desc, col2 desc.
As everybody is comments is discussing the clone and then sort again the list . so here is issue with that approach.
#1. First Set sorting values in Value column for each student :
Value column first contains for each student either 1 or 0 depending on its enrollment date from the cut off date.
#2 Then on same Value column there is CGPA for each student so student should be sorted based on that.
In short all students who apply before cut off date should appear
first and then sort by descending CGPA and then students who apply
after cut off date but those also should come in descending order of
CGPA.
problem is I have only one column here for values, on which need to be sort.
Second edit :
if (_trackConfigManager.RankDependentOnFields.Any())
{
infoFields.ForEach(x => x.PropertyToCompare = _trackConfigManager.RankDependentOnFields.FirstOrDefault().FieldId);
//Order the table withrespect to the firstfield
var orderedFields = infoFields.OrderByDescending(x => x.Value);
//Then skip the first element and order the rest of the fields by descending.
foreach (var field in __trackConfigManager.RankDependentOnFields.RemoveFirst())
{
infoFields.ForEach(x => x.PropertyToCompare = field.FieldId);
orderedFields = orderedFields.ThenByDescending(x => x.Value);
}
//Format a studentId, Rank dictionary from the above orderded table
int rank = 1 + GetMaxRank(programId, statusId);
}
and RankAggregate class as follow :
public class RankAggregate
{
public student_highschool_info HsInfoObj { get; set; }
public student_interview_info IntInfoObj { get; set; }
public student StuObj { get; set; }
private student_program SpObj { get; set; }
public string PropertyToCompare { get; set; }
public bool IsDateTimeField { get; set; }
public long StudentId { get; set; }
public int Choice { get; set; }
public double Value
{
get
{
var tokens = PropertyToCompare.Split(new char[] {':'});
if (tokens.Count() > 1)
{
PropertyToCompare = (Choice == 1)
? "student_interview_FirstPrgTotalScore"
: (Choice == 2) ? "student_interview_SecondPrgTotalScore" : "dummy";
}
var fldInfo = ReflectionUtility.GetPublicPropertyName(typeof(student_highschool_info), PropertyToCompare);
if (fldInfo != null)
{
if (HsInfoObj == null)
return 0;
IsDateTimeField = (fldInfo.PropertyType == typeof(DateTime?));
if (IsDateTimeField)
{
var val1 = ReflectionUtility.GetValueOfPublicProperty(typeof(student_highschool_info),
PropertyToCompare, HsInfoObj) ?? 0;
var dt = DateTime.Parse(val1.ToString());
return -Convert.ToDouble(dt.Ticks);
}
else
{
var val1 = ReflectionUtility.GetValueOfPublicProperty(typeof(student_highschool_info),
PropertyToCompare, HsInfoObj) ?? 0;
return Convert.ToDouble(val1);
}
}
fldInfo = ReflectionUtility.GetPublicPropertyName(typeof(student_interview_info), PropertyToCompare);
if (fldInfo != null)
{
if (IntInfoObj == null)
return 0;
IsDateTimeField = (fldInfo.PropertyType == typeof(DateTime?));
if (IsDateTimeField)
{
var val1 = ReflectionUtility.GetValueOfPublicProperty(typeof(student_interview_info),
PropertyToCompare, IntInfoObj) ?? 0;
var dt = DateTime.Parse(val1.ToString());
return -Convert.ToDouble(dt.Ticks);
}
else
{
var val1 = ReflectionUtility.GetValueOfPublicProperty(typeof(student_interview_info),
PropertyToCompare, this.IntInfoObj) ?? 0;
return Convert.ToDouble(val1);
}
}
fldInfo = ReflectionUtility.GetPublicPropertyName(typeof(student), PropertyToCompare);
if (fldInfo != null)
{
if (StuObj == null)
return 0;
IsDateTimeField = (fldInfo.PropertyType == typeof(DateTime?));
if (IsDateTimeField)
{
var val1 = ReflectionUtility.GetValueOfPublicProperty(typeof(student),
PropertyToCompare, StuObj) ?? 0;
var dt = DateTime.Parse(val1.ToString());
return -Convert.ToDouble(dt.Ticks);
}
else
{
var val1 = ReflectionUtility.GetValueOfPublicProperty(typeof(student),
PropertyToCompare, this.StuObj) ?? 0;
return Convert.ToDouble(val1);
}
}
return 0.0;
}
}
public RankAggregate(long studentId, student_highschool_info _hsInfo, student_interview_info _intInfo, student _profileInfo, student_program _spInfo)
{
StudentId = studentId;
HsInfoObj = _hsInfo;
IntInfoObj = _intInfo;
StuObj = _profileInfo;
SpObj = _spInfo;
if (SpObj != null)
{
Choice = SpObj.choice;
}
}
}
Don't know why can't you add another field to the Student class, anyway since you can't do that, you have to fix these values in some places, for example using a tuple:
var studentsWithValues = students.Select(s => (s, s.Value))
.ToList();
Then after changing the values, you can sort the above array:
var orderedFields = studentsWithValues.OrderByDescending(t => t.Value)
.ThenByDescending(t => t.s.Value)
.Select(t => t.s)
Update for uncertain columns
Bind each student object with a list of values:
var studentsWithValues = students.Select(s => new
{
Student = s,
Values = new List<double> { s.Value }
})
.ToList();
After the values are updated, append each value to the binded list:
UpdateValues();
studentsWithValues.ForEach(t => t.Values.Add(t.Student.Value));
Then you can sort these values:
var e = studentsWithValues.OrderByDescending(t => t.Values[0]);
var valueCount = studentsWithValues.First().Values.Count;
for (int i = 1; i < valueCount; i++)
{
int j = i;
e = e.ThenByDescending(t => t.Values[j]);
}
var orderedFields = e.Select(t => t.Student);
Short answer
Use:
var orderedStudents = students
.OrderByDescending(student => student.Value)
.ToList();
foreach (Student student in orderedStudents) etc.
Longer answer
Your orderedFields is not a list, nor a sequence. It is an object that can be enumerated. It has not been enumerated yet. In other words: it is not a Collection<T>, it is an IEnumerable<T>. Usually in descriptions you'll find the phrases: delayed execution or deferred execution.
When you execute foreach (Student s in orderedFields), you start to enumerate the items in students. You don't enumerate the items in the original order, you enumerate them ordered by .Value.
but as soon I change the Value column values it start to change the order of items in list
So, the next time you enumerate orderedFields, the items in students are enumerated again, and ordered again by the changed value of .Value.
If you want to change the source of the items in your LINQ statement, you have to execute the delayed execution by calling one of the LINQ methods that doesn't return IEnumerable<T>, like ToList(), ToArray(), ToDictionary(), but also FirstOrDefault(), Sum(), Count(), Any()
By calling one of the non-delayed methods, the source is enumerated and the result is put in a new object. If you change the items in the new object, and use this new object as source for your next LINQ-statement, then the order of the new object is used, not the order in the original object.
Careful: if you put the references of the original items in the new List, and you change the values, you change the original items. If you don't want that, use a Select(student => new {...}) to put the values in a new object. If you change those values, the original students are not affected.

Display count of task for each id

I have page where i display list of tasks (with Jquery DataTable) and i want display Employee name with count of thire tasks. for example:
Smith (2) | John (1) | Thomas (1)
Tables:
AssignName:
Tasks (AssignId as ForeignKey):
Here what i did :
Here i get List of tasks and select some properties:
var Taskslist = db.Tasks.Select(g => new ServicetasksVM.ItemGroup
{
OpgaveServicesId = g.Id,
Opgaver = g.Opgaver,
Opgaveid = g.Id,
Opretteaf = g.Opretteaf,
OpretteDato = g.OpretteDato,
}).AsEnumerable();
Her iterating over the results to get count each id:
foreach (var item in result)
{
var AssignCount = db.AssignName.Where(c => c.Id == item.Assingid)
.GroupBy(x => x.Name)
.Select(b => new ServicetasksVM.ItemGroup { Assingid = b.Count(), EmployeeNames= b.Key });
}
Put all code together (for simplicity i remove unneeded code):
public JsonResult ListofTasks() {
var Taskslist = db.Tasks.Select(g => new ServicetasksVM.ItemGroup
{
OpgaveServicesId = g.Id,
Opgaver = g.Opgaver,
Opgaveid = g.Id,
Opretteaf = g.Opretteaf,
OpretteDato = g.OpretteDato,
}).AsEnumerable();
var result = Taskslist.Skip(start).Take(length).ToList();
foreach (var item in result)
{
var AssignCount = db.AssignName.Where(c => c.Id == item.Assingid)
.GroupBy(x => x.Name)
.Select(b => new ServicetasksVM.ItemGroup { Assingid = b.Count(), EmployeeNames= b.Key });
}
JsonResult json = Json(new { data = result, draw = Request["draw"], recordsTotal = totalrows, recordsFiltered = totalrowsefterfiltering }, JsonRequestBehavior.AllowGet);
json.MaxJsonLength = int.MaxValue;
return json;
ViewModel:
public List<ItemGroup> ItemGroups { get; set; }
public class ItemGroup
{
public ItemGroup()
{
}
public int OpgaveServicesId { get; set; }
public string Opgaver { get; set; }
public string Opretteaf { get; set; }
public DateTime? OpretteDato { get; set; }
public int Opgaveid { get; set; }
public int OpgaveSmartid { get; set; }
public string Opgavestatus { get; set; }
public int? Assingid { get; set; }
public string EmployeeNames { get; set; }
}
In the end when I check the results both Assingid and EmployeeNames are null. Can anyone please help me :)
Scope of AssignCount variable is limited to foreach loop, that is the reason you are getting Assingid and EmployeeNames as a null at the end of program.
To fix this issue, store each AssignCount to the list, so that you can access all counts out of foreach loop
...
//Define list of List of ItemGroup, as AssignCount is of type List<ItemGroup>
List<List<ServicetasksVM.ItemGroup>> itemGroups = new List<List<ServicetasksVM.ItemGroup>>();
foreach (var item in result)
{
var AssignCount = db.AssignName.Where(c => c.Id == item.Assingid)
.GroupBy(x => x.Name)
.Select(b => new ServicetasksVM.ItemGroup { Assingid = b.Count(), EmployeeNames= b.Key })
.ToList(); //Convert To List
itemGroups.Add(AssignCount); //Add each `AssignCount` to itemGroups
}
//Now list of AssignCount(s) is(are) accessible outside foreach loop
...
Your for loop is doing the counting and assigning it to the variable AssignCount which only exists in the scope of the for loop. You need to capture that result in a variable that is outside the scope of the loop to pass that along to your view.
Something like:
var itemGroups = new List<ItemGroup>();
foreach (var item in result)
{
var AssignCount = db.AssignName.Where(c => c.Id == item.Assingid)
.GroupBy(x => x.Name)
.Select(b => new ServicetasksVM.ItemGroup { Assingid = b.Count(), EmployeeNames= b.Key });
itemGroups.Add(AssignCount);
}
variable AssignCount is local in the foreach loop. better create collection outside of the loop and keep on adding to it inside the loop.

Count elements of an array only using Linq?

I have the 3 classes Item, Order and Management.
Order has an array with ordered Items, Management has a List of different Orders. How can I display the number of ordered items for all PurchaseOrders with the given name?
For example: Item1 is ordered 2 times with quantity = 5 and 2 times with quantity = 7, so the total number is 2*5+2*7=24.
I can solve the task, but only Linq should be used without loops, etc.
class MainClass
{
public static void Main(string[] args)
{
Management Management = new Management();
Management.PrintQuantityForSingleItem("Item1");
}
}
class Item
{
public string Name { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
public Item(string Name, decimal Price, int Quantity)
{
this.Name = Name;
this.Price = Price;
this.Quantity = Quantity;
}
}
class Order
{
public int Id { get; set; }
public Item[] Items { get; set; }
public Order(int Id, Item[] Items)
{
this.Id = Id;
this.Items = Items;
}
}
class Management
{
public List<Order> Orders { get; set; }
public Management()
{
Item i1 = new Item("Item1", 2.0M, 5);
Item i2 = new Item("Item2", 3.0M, 6);
Item i3 = new Item("Item1", 2.0M, 7);
Orders = new List<Order>()
{
new Order(1, new Item[]{i1, i2}),
new Order(2, new Item[]{i3}),
new Order(3, new Item[]{i1, i3}),
};
}
//displays the total number of ordered items for all Orders with the given name on the console.
public void PrintQuantityForSingleItem(string itemName)
{
var result = (from x in Orders
select x.Items).ToList();
int counter = 0;
for (int i = 0; i < result.Count(); i++)
{
for (int a = 0; a < result[i].Count(); a++)
{
if (result[i][a].Name == itemName)
{
counter = counter + result[i][a].Quantity;
}
Console.WriteLine(result[i][a].Name);
}
}
Console.WriteLine(itemName + " " + counter);//for example: shows 24 for item1
}
}
You'll need to select all order items, group them by name and then calculate the sum value for the Quantity. The final step is to get the calculated sum value by item name and display it
public void PrintQuantityForSingleItem(string itemName)
{
var results = Orders
.SelectMany(o => o.Items)
.GroupBy(i => i.Name)
.Select(g => new { Item = g.Key, Sum = g.Sum(i => i.Quantity) });
var item = results.FirstOrDefault(r => r.Item.Equals(itemName, StringComparison.OrdinalIgnoreCase));
Console.WriteLine(itemName + " " + item?.Sum);//shows 24 for item1
}
Welcome to SO. It is obviously not advisable to look up items by name, but ignoring aspects of the design, here is one way of doing it:
var result = Orders.SelectMany(i => i.Items)
.Where(i => i.Name == itemName)
.Sum(i => i.Quantity);
Console.WriteLine($"{itemName}: {result}"); //24
Output:
Item1: 24
You can try the following,
public void PrintQuantityForSingleItem(string itemName)
{
var res = Orders.Select(x=>x.Items).Sum(y => y.Where(z => z.Name == itemName).Sum(t => t.Quantity));
Console.WriteLine(res);
Console.ReadKey();
}
It prints 24
You can use Linq :
decimal counter = Orders
.SelectMany(o => o.Items)
.Where(i => i.Name == itemName)
.Sum(i => i.Quantity);
I hope you find this helpful.

Best approach to compare if one list is subset of another in C#

I have the below two classes:
public class FirstInner
{
public int Id { get; set; }
public string Type { get; set; }
public string RoleId { get; set; }
}
public class SecondInner
{
public int Id { get; set; }
public string Type { get; set; }
}
Again, there are lists of those types inside the below two classes:
public class FirstOuter
{
public int Id { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public List<FirstInner> Inners { get; set; }
}
public class SecondOuter
{
public int Id { get; set; }
public string Name { get; set; }
public List<SecondInner> Inners { get; set; }
}
Now, I have list of FirstOuter and SecondOuter. I need to check if FirstOuter list is a subset of SecondOuter list.
Please note:
The names of the classes cannot be changed as they are from different systems.
Some additional properties are present in FirstOuter but not in SecondOuter. When comparing subset, we can ignore their presence in SecondOuter.
No.2 is true for FirstInner and SecondInner as well.
List items can be in any order---FirstOuterList[1] could be found in SecondOuterList[3], based on Id, but inside that again need to compare that FirstOuterList[1].FirstInner[3], could be found in SecondOuterList[3].SecondInner[2], based on Id.
I tried Intersect, but that is failing as the property names are mismatching. Another solution I have is doing the crude for each iteration, which I want to avoid.
Should I convert the SecondOuter list to FirstOuter list, ignoring the additional properties?
Basically, here is a test data:
var firstInnerList = new List<FirstInner>();
firstInnerList.Add(new FirstInner
{
Id = 1,
Type = "xx",
RoleId = "5"
});
var secondInnerList = new List<SecondInner>();
secondInner.Add(new SecondInner
{
Id = 1,
Type = "xx"
});
var firstOuter = new FirstOuter
{
Id = 1,
Name = "John",
Title = "Cena",
Inners = firstInnerList
}
var secondOuter = new SecondOuter
{
Id = 1,
Name = "John",
Inners = secondInnerList,
}
var firstOuterList = new List<FirstOuter> { firstOuter };
var secondOuterList = new List<SecondOuter> { secondOuter };
Need to check if firstOuterList is part of secondOuterList (ignoring the additional properties).
So the foreach way that I have is:
foreach (var item in firstOuterList)
{
var secondItem = secondOuterList.Find(so => so.Id == item.Id);
//if secondItem is null->throw exception
if (item.Name == secondItem.Name)
{
foreach (var firstInnerItem in item.Inners)
{
var secondInnerItem = secondItem.Inners.Find(sI => sI.Id == firstInnerItem.Id);
//if secondInnerItem is null,throw exception
if (firstInnerItem.Type != secondInnerItem.Type)
{
//throw exception
}
}
}
else
{
//throw exception
}
}
//move with normal flow
Please let me know if there is any better approach.
First, do the join of firstOuterList and secondOuterList
bool isSubset = false;
var firstOuterList = new List<FirstOuter> { firstOuter };
var secondOuterList = new List<SecondOuter> { secondOuter };
var jointOuterList = firstOuterList.Join(
secondOuterList,
p => new { p.Id, p.Name },
m => new { m.Id, m.Name },
(p, m) => new { FOuterList = p, SOuterList = m }
);
if(jointOuterList.Count != firstOuterList.Count)
{
isSubset = false;
return;
}
foreach(var item in jointOuterList)
{
var jointInnerList = item.firstInnerList.Join(
item.firstInnerList,
p => new { p.Id, p.Type },
m => new { m.Id, m.type },
(p, m) => p.Id
);
if(jointInnerList.Count != item.firstInnerList.Count)
{
isSubset = false;
return;
}
}
Note: I am assuming Id is unique in its outer lists. It means there will not be multiple entries with same id in a list. If no, then we need to use group by in above query
I think to break the question down..
We have two sets of Ids, the Inners and the Outers.
We have two instances of those sets, the Firsts and the Seconds.
We want Second's inner Ids to be a subset of First's inner Ids.
We want Second's outer Ids to be a subset of First's outer Ids.
If that's the case, these are a couple of working test cases:
[TestMethod]
public void ICanSeeWhenInnerAndOuterCollectionsAreSubsets()
{
HashSet<int> firstInnerIds = new HashSet<int>(GetFirstOuterList().SelectMany(outer => outer.Inners.Select(inner => inner.Id)).Distinct());
HashSet<int> firstOuterIds = new HashSet<int>(GetFirstOuterList().Select(outer => outer.Id).Distinct());
HashSet<int> secondInnerIds = new HashSet<int>(GetSecondOuterList().SelectMany(outer => outer.Inners.Select(inner => inner.Id)).Distinct());
HashSet<int> secondOuterIds = new HashSet<int>(GetSecondOuterList().Select(outer => outer.Id).Distinct());
bool isInnerSubset = secondInnerIds.IsSubsetOf(firstInnerIds);
bool isOuterSubset = secondOuterIds.IsSubsetOf(firstOuterIds);
Assert.IsTrue(isInnerSubset);
Assert.IsTrue(isOuterSubset);
}
[TestMethod]
public void ICanSeeWhenInnerAndOuterCollectionsAreNotSubsets()
{
HashSet<int> firstInnerIds = new HashSet<int>(GetFirstOuterList().SelectMany(outer => outer.Inners.Select(inner => inner.Id)).Distinct());
HashSet<int> firstOuterIds = new HashSet<int>(GetFirstOuterList().Select(outer => outer.Id).Distinct());
HashSet<int> secondInnerIds = new HashSet<int>(GetSecondOuterList().SelectMany(outer => outer.Inners.Select(inner => inner.Id)).Distinct());
HashSet<int> secondOuterIds = new HashSet<int>(GetSecondOuterList().Select(outer => outer.Id).Distinct());
firstInnerIds.Clear();
firstInnerIds.Add(5);
firstOuterIds.Clear();
firstOuterIds.Add(5);
bool isInnerSubset = secondInnerIds.IsSubsetOf(firstInnerIds);
bool isOuterSubset = secondOuterIds.IsSubsetOf(firstOuterIds);
Assert.IsFalse(isInnerSubset);
Assert.IsFalse(isOuterSubset);
}
private List<FirstOuter> GetFirstOuterList() { ... }
private List<SecondOuter> GetSecondOuterList() { ... }

How improve add items under the List, when i have more than 2 elements

The next code is functional, but I want know if exist a better way to do this function.
With linq I get a list with 4 elements, but I needed add those elements in a list of ProposalItems, the next code is the type of the list
private class ProposalItems
{
public double Quantity { get; set; }
public double Price { get; set; }
public int Row { get; set; }
public double Total { get; set; }
}
And the next code is the method:
internal List<ProposalItems> GetProposalItems(int tradeId, int contendantId)
{
using (var db = new Entities())
{
//declare the list
List<ProposalItems> items = new List<ProposalItems>();
//query in linq
var data = db.ES_SC_PropuestasPrecios
.Join(db.ES_SC_CatalogoConceptos,
prices => prices.renglon,
concept => concept.renglon,
(prices, concept) => new { ES_SC_PropuestasPrecios = prices, ES_SC_CatalogoConceptos = concept })
.Where(w => w.ES_SC_CatalogoConceptos.idconcurso == tradeId && w.ES_SC_PropuestasPrecios.idconcursante == contendantId)
//select the items
.Select(s => new
{
Row = s.ES_SC_CatalogoConceptos.renglon,
Quantity = s.ES_SC_CatalogoConceptos.cantidad,
Price = s.ES_SC_PropuestasPrecios.preciounitario,
Total = s.ES_SC_PropuestasPrecios.importe
}).ToList();
// loop to add the item in the list
foreach (var item in data)
{
items.Add(new ProposalItems { Row = (int)item.Row, Price = (double)item.Price, Quantity = (double)item.Quantity, Total = (double)item.Total });
}
return items;
}
}
Try to substitute your current select for this
.Select(s => new ProposalItems {
Row = (int)s.ES_SC_CatalogoConceptos.renglon,,
Price = (double)s.ES_SC_PropuestasPrecios.preciounitario,
Quantity = (double)s.ES_SC_CatalogoConceptos.cantidad,
Total = (double)s.ES_SC_PropuestasPrecios.importe
}).ToList();

Categories