I just asked a question about my class:
Public class Parent {
public IList<ParentDetail> ParentDetails {
get { return _ParentDetails; }
}
private List<ParentDetail> _ParentDetails = new List<ParentDetail>();
public Parent() {
this._ParentDetails = new List<ParentDetail>();
}
}
public class ParentDetail {
public int Id { get; set; }
}
}
One of the experts here (Jon) told me how I could iterate through this class in order of the ParentDetails.Id. Here's his solution which works good.
Previous question
foreach(var details in Model.Parent.ParentDetails.OrderBy(d => d.Id))
{
// details are processed in increasing order of Id here
// what's needed is to get access to the original order
// information. Something like as follows:
// select index position from ParentDetails where Id = details.ID
}
What I also need is within this foreach to show the index value of the list corresponding to the Id along with some other data that's in the ParentDetail class.
So for example where it says // details are processed then I want to be able to print out the index value that corresponded to the current Id in the foreach loop.
Use the second Enumerable.Select method:
foreach(var details in Model.Parent.ParentDetails
.Select((value, idx) => new { Index = idx, Value = value })
.OrderBy(d => d.Value.Id)
)
{
// details are processed in increasing order of Id here
Console.WriteLine("{0}: {1}", details.Index, details.Value);
}
This is assuming you wanted the indices to be in the original order.
You can use a regular for for that.
var ordered = Model.Parent.ParentDetails.OrderBy(d => d.Id).ToList();
for(int i = 0; i < ordered.Count; i++)
{
// details are processed in increasing order of Id here
}
Related
I am trying to filter from attachList the taxheaderID, it comes from my database which is structured as such.
public int attachmentID { get; set; }
public int headerID { get; set; }
public string uploadedfilename { get; set; }
public string originalfilename { get; set; }
public string foldername { get; set; }
Here is the code that gets data from the database:
public JsonResult GetAllAttach()
{
using (car_monitoringEntities contextObj = new car_monitoringEntities())
{
var attachList = contextObj.car_taxcomputationattachment.ToList();
return Json(attachList, JsonRequestBehavior.AllowGet);
}
}
These are my attempts:
attachList
.Select(x => x.headerID)
.Where(x => x == x)
.Take(1);
and:
attachList = attachList
.Where(al => attachList
.Any(alx => al.taxheaderID == alx.headerID
&& al.headerID == alx.headerID));
The problem is I want to parse multiple attach on a single headerID or filter them base on headerID. For example:
Problem to fix:
This is the table
Desired output:
Combined
data table:
data table
data table 2
Here is the actual solution that was made to get the output, but my coworker told me that it is not a good practice that's why I'm trying to filter it in the function itself. apologies for the trouble, thanks!
<div ng-repeat="att in attach|filter:{headerID:header.headerID}:true">
{{att.uploadedfilename}} <br />
</div>
To get attachments by Id
public JsonResult GetAllAttach(int headerId)
{
using (car_monitoringEntities contextObj = new car_monitoringEntities())
{
var attachList = contextObj.car_taxcomputationattachment
.Where(x => x.headerID == headerId)
.ToList();
return Json(attachList, JsonRequestBehavior.AllowGet);
}
}
If you want to have all data in one JSON result, then you need to create a nested view model.
Assuming you have the header id on which you want to filter in a local variable, you are almost correct
int headerIdToFind = 19;
// think of x as a local variable inside a foreach loop which
// iterates over each item in the attachList (it does not exist
// outside the where method)
// this is what you got wrong when you compared the item to itself
var filteredAttach = attachList.Where(x => x.headerId = headerIdToFind);
// if you want to select only some properties based on header id
// you can use select to project those properties
var filteredAttach = attachList.Where(x => x.headerId = headerIdToFind).
Select(x => new {x.attachmentId, x.folderName});
// based on last image, you only want to select (project) header id and the
// filename. so you do not need where (filter) at all
// you can put all the properties you need in the select clause
var filteredAttach = attachList.Select(x => new {x.headerId, x.attachmentId});
// you can enumerate the filtered attach list of convert it into a list
var filteredAttach = filteredAttach.ToList();
I am trying to use Group By method supported by LINQ.
I have this class
public class Attribute
{
public int Id {get;set;}
public string Name {get;set;}
public string Value {get;set;}
}
I have a service method that will retrive a IList
var attributes = _service.GetAll();
Id Name Value
7 Color Black
7 Color White
220 Size 16
Now I have another tow classes
one is
public class AttributeResourceModelSubItem
{
public string Name {get;set;}
public List<AttributeValueResourceModelSubItem> values { get; set; }
}
public class AttributeValueResourceModelSubItem
{
public int Id;
public string Name {get;set;}
}
I am trying to loop through the attributes list. and if the attribute id is the same, I wanna insert the records where id = to that id inside the AttributeValueResourceModelSubItem in which id = 1 and Name will be equal to the attribute value.
This what I got so far.
private IList<AttributeResourceModelSubItem> FormatAttributes(IList<Attribute> attributes)
{
Dictionary<int, Attribute> baseTypes = new Dictionary<int, Attribute>();
AttributeResourceModelSubItem attributeResourceModelSubItem = null;
var list = new IList<AttributeResourceModelSubItem>();
foreach (var item in attributes)
{
if (!baseTypes.ContainsKey(item.Id))
{
attributeResourceModelSubItem = new AttributeResourceModelSubItem()
attributeResourceModelSubItem.key = item.Name;
attributeResourceModelSubItem.values.Add(new AttributeValueResourceModelSubItem()
{
id = 1,
name = item.Value
});
list.Add(attributeResourceModelSubItem);
}
baseTypes.Add(item.Id, item);
}
return list;
}
Any help is appreciated.
It's pretty unclear from your example what you're actually trying to do, but this is the gist I get.
private IEnumerable<AttributeResourceModelSubItem> FormatAttributes(IEnumerable<Attribute> attributes)
{
return attributes.GroupBy(c => c.Id)
.Select(c => new AttributeResourceModelSubItem()
{
key = c.First().Name,
values = c.Select(x => new AttributeValueResourceModelSubItem()
{
id = 1,
name = x.value
}).ToList();
});
}
You should also definitely not use the word Attribute as a class name. That's already a .NET class.
I'll admit that I don't quite understand the id = 1 part, but I took that from your code. It also seems odd to group by the id then try and take the first name, but again that's what you have.
If you do, in fact, want to group by the name and take the id, which makes a little more sense, you'll want to swap a couple things around. Admittedly this structure still seems a little odd to me, but hopefully this will get you a couple steps closer to your goal.
private IEnumerable<AttributeResourceModelSubItem> FormatAttributes(IEnumerable<Attribute> attributes)
{
return attributes.GroupBy(c => c.name)
.Select(c => new AttributeResourceModelSubItem()
{
key = c.Key,
values = c.Select((item, index) => new AttributeValueResourceModelSubItem()
{
id = index + 1,
name = item.value
}).ToList();
});
}
I also made your id = 1 increment starting at one for each element in each values list. You might want that to be item.Id, or even just your original 1.
I have this class:
public class Document
{
public string ID { get; set; }
public string Type { get; set; }
public bool Checked {get;set; }
}
I create a set of 10 elements using Enumerable.Repeat static method:
var list = Enumerable.Repeat<Document>(
new Document
{
ID="1",
Type ="someType"
Checked = true
}, 10).ToList<Document>();
These creates 10 Documents all with the same properties. I need that some of them, for instance, the first 5 elements of the list list have the Checked property to false.
How can I achieve it, using as possible linq?
Note that your original sample has a bug because it's creating a 10 element List<Document> that only has 1 actual Document object. Here is a better way of doing it
Enumerable
.Range(1, 10)
.Select(i =>
new Document() {
ID = "1",
Type = "someType",
Checked = i <= 5
})
.ToList();
EDIT
Changed the code to be simpler. My original response was to editing an already existing list for which the following can be done
list.Take(5).ForEach(x => { x.Checked = false });
Note that you may have to define a simple ForEach method for this operation. If you don't have one defined here is an example
static class Extensions {
internal static void ForEach<T>(this IEnumerable<T> e, Action<T> action) {
foreach (var item in e) {
action(item);
}
}
}
Alternate idea to accomplish what you're asking for (also populates your ID column with something other than "1"):
var list = Enumerable.Range(1, 10)
.Select(i => new Document
{
ID = i.ToString(),
Type = "someType",
Checked = (i > 5)
}).ToList();
I am trying to add elements into a list, order them and then output them, there a number of "columns" if you like, per list
List<Info> infoList = new List<Info>();
while (dr.Read())
{
meeting_id = dr.GetValue(0).ToString();
try
{
Appointment appointment = Appointment.Bind(service, new ItemId(meeting_id));
Info data = new Info();
data.Start = appointment.Start;
data.Fruit = Convert.ToInt32(dr.GetValue(1));
data.Nuts = Convert.ToInt32(dr.GetValue(2));
infoList.Add(data);
}
Then to output it I want to order it by Start and then display all associated columns
for (int i = 0; i < infoList.Count; i++)
{
meet = meet + infoList[i];
}
First question: is the way I am inputting the data right?
Second question: How to I output all the columns to display all the associated columns? Is this possible? Is there a better practice?
Thanks
EDIT:
The class if you are interested:
public class Info
{
public DateTime Start { get; set; }
public int Fruit { get; set; }
public int Nuts { get; set; }
}
You can use Enumerable.OrderBy extension for enumerating your collection in some particular order (e.g. ordered by Start property value):
foreach(var info in infoList.OrderBy(i => i.Start))
{
// use info object here
// info.Fruits
// info.Nuts
}
BTW consider to add sorting on database side - that will be more efficient
There's a list of objects, each object representing a record from a database. To sort the records there is a property called SortOrder. Here's a sample object:
public class GroupInfo
{
public int Id { get; set; }
public string Text { get; set; }
public int SortOrder { get; set; }
public GroupInfo()
{
Id = 0;
Text = string.Empty;
SortOrder = 1;
}
}
A list object would look like this:
var list = new List<GroupInfo>();
I need to be able to change the SortOrder and update the SortOrder on the other objects in the list. I figured out how to sort up or down by one. I need to know how to change it by more than one and adjust the SortOrder on the other records. Any ideas?
This could be done by first getting the original SortOrder and the updated SortOrder. You would then iterate through your collection and adjust the SortOrder of any other GroupInfo objects that fall inside the range between original and updated. you could put all of this in a "SetSortOrder" function that takes in the containing collection.
public static void SetSortOrder(List<GroupInfo> groupInfos, GroupInfo target, int newSortOrder)
{
if (newSortOrder == target.SortOrder)
{
return; // No change
}
// If newSortOrder > SortOrder, shift all GroupInfos in that range down
// Otherwise, shift them up
int sortOrderAdjustment = (newSortOrder > target.SortOrder ? -1 : 1);
// Get the range of SortOrders that must be updated
int bottom = Math.Min(newSortOrder, target.SortOrder);
int top = Math.Max(newSortOrder, target.SortOrder);
// Get the GroupInfos that fall within our range
var groupInfosToUpdate = from g in groupInfos
where g.Id != target.Id
&& g.SortOrder >= bottom
&& g.SortOrder <= top
select g;
// Do the updates
foreach (GroupInfo g in groupInfosToUpdate)
{
g.SortOrder += sortOrderAdjustment;
}
target.SortOrder = newSortOrder;
// Uncomment this if you want the list to resort every time you update
// one of its members (not a good idea if you're doing bulk changes)
//groupInfos.Sort((info1, info2) => info1.SortOrder.CompareTo(info2.SortOrder));
}
Update: As suggested, I moved the logic into a static helper function.
var sortedList = list.OrderBy(item => item.SortOrder);
Edit: Sorry, I misunderstood. You will need to write yourself a method outside of GroupInfo to handle the updating of that property.