In my project I use an XML to import various instances of a class.
I need to import in a List.
The problem is how to import all "dynamicDrop" in a Dictionary:
XML:
<LootProfile name="volpeNormale">
<dynamicDropNumber>3</dynamicDropNumber>
<dynamicDrop>70</dynamicDrop>
<dynamicDrop>40</dynamicDrop>
<dynamicDrop>10</dynamicDrop>
<dynamicTypeArmor>33</dynamicTypeArmor>
<dynamicTypeWeapon>33</dynamicTypeWeapon>
<dynamicTypeConsumable>34</dynamicTypeConsumable>
<dynamicRarityCommon>70</dynamicRarityCommon>
<dynamicRarityUncommon>20</dynamicRarityUncommon>
<dynamicRarityRare>8</dynamicRarityRare>
<dynamicRarityEpic>2</dynamicRarityEpic>
<staticDropNumber>2</staticDropNumber>
<staticDrop idPattern="100">60</staticDrop>
<staticDrop idPattern="145">100</staticDrop>
<faction>All</faction>
<location>All</location>
</LootProfile>
XMLImporter query:
var query = from item in xml.Root.Elements("LootProfile")
select new LootProfile()
{
name = (string)item.Attribute("name"),
dynamicDropNumber = (int)item.Element("dynamicDropNumber"),
dynamicDrop = (Dictionary<int,string>)item.Element("dynamicDrop) //this one doesnt work!
//other element....
}
return query.ToList<LootProfile>();
Here is how you can do it:
var query = xml.Elements("LootProfile")
.Select(item => new LootProfile()
{
name = (string) item.Attribute("name"),
dynamicDropNumber = (int) item.Element("dynamicDropNumber"),
dynamicDrop =
item.Elements("dynamicDrop")
.Select((Item, Index) => new {Item, Index})
.ToDictionary(x => x.Index, x => float.Parse(x.Item.Value))
//other element....
});
var result = query.ToList();
The trick is to use an overload of Select that gives you two lambda parameters; the item itself, and the index of the item.
Related
I've a Key/Value table in my DB and I would return a List of Dictionary.
The following code works fine for me but with a lot of data is not performing.
note: r.name doesn't contains unique value
List<Dictionary<string, string>> listOutput = null;
using (ExampleDB db = new ExampleDB())
{
var result = (from r in db.FormField
where r.Form_id == 1
select new { r.ResponseId, r.name, r.value}).toList();
listOutput = new List<Dictionary<string, string>>();
foreach (var element in result)
{
listOutput.Add((from x in listOutput
where x.ResponseId == element.ResponseId
select x).ToDictionary(x => x.name, x => x.value));
}
}
return listOutput;
Do you have suggestions on how to improve this code ?
I suspect you want something like:
List<Dictionary<string, string>> result;
using (var db = new ExampleDB())
{
result = db.FormField
.Where(r => r.Form_id == 1)
.GroupBy(r => r.ResponseId, r => new { r.name, r.value })
.AsEnumerable()
.Select(g => g.ToDictionary(p => p.name, p => p.value))
.ToList();
}
In other words, we're filtering so that r.Form_id == 1, then grouping by ResponseId... taking all the name/value pairs associated with each ID and creating a dictionary from those name/value pairs.
Note that you're losing the ResponseId in the list of dictionaries - you can't tell which dictionary corresponds to which response ID.
The AsEnumerable part is to make sure that the last Select is performed using LINQ to Objects, rather than trying to convert it into SQL. It's possible that it would work without the AsEnumerable, but it will depend on your provider at the very least.
From what I gather you're trying to create a list of Key/Value pairs based on each ResponseId. Try GroupBy:
var output = result.GroupBy(r => r.ResponseId)
.Select(r => r.ToDictionary(s => s.Name, s => s.Value));
This will return an IEnumerable<Dictionary<string,string>>, which you can ToList if you actually need a list.
This linq query works well.
var qry = context.Boxes
.GroupBy(k=>k.Box_ID)
.Select( group => new {
Box_ID = group.Key,
TotalA = group.Sum(p => p.A),
TotalC = group.Sum(p => p.C)
})
.Select(p => new {
Box_ID = p.Kasa_ID,
TotalA = p.TotalA,
TotalC = p.TotalC,
DiffAC = p.TotalA - p.TotalC
});
But, i saw these type select statements, second one uses first select's anonymous type result, written like this:
var qry = context.Boxes
.GroupBy(k => k.Box_ID)
.Select(group => new
{
Box_ID = group.Key,
TotalA = group.Sum(p => p.A),
TotalC = group.Sum(p => p.C)
})
.Select(p => new
{
Box_ID, //*** compiler error
TotalA, //I'm asking about these 3 lines, is this syntax possible
TotalC, //TotalC = p.TotalC,
DiffAC = p.TotalA - p.TotalC // calculate
});
comments contains details.
When i try to compile second query, compiler gives me the error "The name 'Box_ID' does not exist in the current contex".
In fact there is no doubt with first syntax, but second one is more readable. How can i use second syntax? or in which condititons i can use it.
.Select(p => new
{
p.Box_ID,
p.TotalA,
p.TotalC,
DiffAC = p.TotalA - p.TotalC // calculate
});
I have a list Having multiple Items and 3 props ID,DATE,COMMENT.ID field is Auto incremented in DATABASE.
Let say list Contains
2,16AUG,CommentMODIFIED
1,15AUG,CommentFIRST
3,18AUG,CommentLASTModified
I want to get a single ITEM.Item Having Minimum DATE and having Latest Comment. In this case
1,15AUG,CommentLASTModified
Any easy way to do it using LINQ.
orderedItems = items.OrderBy(x => x.Date);
var result = items.First();
result.Comment = items.Last().Comment;
To get a single item out of the list, you can order the items then take the first one, like this:
var result = items
.OrderByDescending(x => x.Date)
.First();
But First will throw an exception if the items collection is empty. This is a bit safer:
var result = items
.OrderByDescending(x => x.Date)
.FirstOrDefault();
To get the min / max of different columns you can do this:
var result =
new Item {
Id = 1,
Date = items.Min(x => x.Date),
Comment = items.Max(x => x.Comment)
};
But this will require two trips to the database. This might be a bit more efficient:
var result =
(from x in items
group x by 1 into g
select new Item {
Id = 1,
Date = g.Min(g => g.Date),
Comment = g.Max(g => g.Comment)
})
.First();
Or in fluent syntax:
var result = items
.GroupBy(x => 1)
.Select(g => new Item {
Id = 1,
Date = g.Min(g => g.Date),
Comment = g.Max(g => g.Comment)
})
.First();
How to change the following linq query to select another field value Field<int>("data_entry"),i want to select multiple fields .
var a = DF_Utilities.GetAvailableTasks(empnum, 1).AsEnumerable().Where(
p => p.Field<int>("task_code") == int.Parse(drpTasks.SelectedValue)).Select(p => p.Field<int>("cand_num")).First();
p.Field<int>("cand_num"),Field<int>("data_entry")
instead of p.Field<int>("cand_num")
You can use anonymous type:
var a = DF_Utilities.
GetAvailableTasks(empnum, 1).
AsEnumerable().
Where(p => p.Field<int>("task_code") == int.Parse(drpTasks.SelectedValue)).
Select(p => new
{
candNum = p.Field<int>("cand_num"),
dataEntry = p.Field<int>("data_entry")
}).
First();
I am currently using Linq to retrieve a list of distinct values from my data table. I am then looping through the list and again calling a linq query to retrieve a list of values for each
value in the first list.
_keyList = new SortedList<int, List<int>>();
var AUGroupList = ProcessSummaryData.AsEnumerable()
.Select(x => x.Field<int>("AUGroupID"))
.Distinct()
.ToList<int>();
foreach (var au in AUGroupList)
{
var AUList = ProcessSummaryData.AsEnumerable()
.Where(x => x.Field<int>("AUGroupID") == au)
.Select(x => x.Field<int>("ActivityUnitID"))
.ToList<int>();
_keyList.Add(au, AUList);
}
I am then adding the value to a sorted list along with the corresponding second list.
How can I combine the above two queries into one Linq query so that I don't have to call them separately?
You should be able to do something like:
var groupQuery = from d in ProcessSummary.AsEnumerable()
group d by new { Key = d.Field<int>("AUGroupID") } into g
select new { GroupID = g.Key, Values = g.Distinct().ToList() };
Then you can loop through the groupQuery and populate the sorted list. The Key property will contain the group id, and the Values property will have a distinct list of values.
Have you tried this?
var _keyList = new SortedList<int, List<int>>();
var AUGroupList = ProcessSummaryData.AsEnumerable()
.Select(x => x.Field<int>("AUGroupID"))
.Distinct()
.Where(x => x.Field<int>("AUGroupID") == au)
.Select(x => x.Field<int>("ActivityUnitID"))
.ToList<int>();
_keyList.Add(au, AUList);
}
Your provider should cope with that, if not there's a few other ways.