Java - How to create a new map containing summed fields from a map containing a key and list of fields - dictionary

I am provided with a List<Result>
The Result class has a number of fields of which five are of interest
class Result {
public enum SESSION_TYPE {
NIGHT,
DAY
}
private SESSION_TYPE sessionType;
private String sessionDateTime;
private String sessionDate;
private Double consumed;
private Double cost;
...
getters and setters
}
I have created a map as follows
Map<String,List<Result>> dailyResults = results.stream().collect(Collectors.groupingBy(Result::getSessionDate));
I would now like to create a new map keyed on the same sessionDate which contains the summed consumed and cost fields grouped by the SESSION_TYPE, thus
Map<String, Map<String,SessionDetail>> sessionResults
i.e.,
Map<SessionDate, Map<SessionType,SessionDeatail>>
where the SessionDetail is a record as follows -
record SessionDetail(Result.SESSION_TYPE sessionType, Double consumedTotal, Double costTotal) {};
I've spent some time on this without achieving the desired result. Any help would be much appreciated.

You can do as follows:
Here is some data.
List<Result> results = new ArrayList<>(List.of(
new Result(Result.SESSION_TYPE.DAY, "T1", "27-Dec-2022", 10., 1.),
new Result(Result.SESSION_TYPE.DAY, "T1", "27-Dec-2022", 10., 2.),
new Result(Result.SESSION_TYPE.DAY, "T1", "27-Dec-2022", 10., 3.),
new Result(Result.SESSION_TYPE.NIGHT, "T1", "26-Dec-2022", 10., 20.),
new Result(Result.SESSION_TYPE.NIGHT, "T1", "26-Dec-2022", 10., 30.),
new Result(Result.SESSION_TYPE.DAY, "T1", "26-Dec-2022", 10., 40.),
new Result(Result.SESSION_TYPE.DAY, "T1", "27-Dec-2022", 10., 10.),
new Result(Result.SESSION_TYPE.DAY, "T1", "27-Dec-2022", 10., 10.)));
The original results can be first categorized by the Date. Then using toMap,
take the session type as the key and then create a new instance, summing the values in the previous instance to the one just encountered.
Map<String, Map<Result.SESSION_TYPE, SessionDetail>> dailyResults = results
.stream()
.collect(Collectors.groupingBy(Result::getSessionDate,
Collectors.toMap(Result::getSessionType,
r -> new SessionDetail(r.getSessionType(),
r.getConsumed(), r.getCost()),
(a, b) -> new SessionDetail(b.sessionType,
a.consumedTotal + b.consumedTotal,
a.costTotal + b.costTotal))));
Print the results as follows:
dailyResults.entrySet().forEach(e -> {
System.out.println(e.getKey());
e.getValue().entrySet()
.forEach(s -> System.out.println(" " + s));
});
prints
27-Dec-2022
DAY=SessionDetail[sessionType=DAY, consumedTotal=50.0, costTotal=26.0]
26-Dec-2022
NIGHT=SessionDetail[sessionType=NIGHT, consumedTotal=20.0, costTotal=50.0]
DAY=SessionDetail[sessionType=DAY, consumedTotal=10.0, costTotal=40.0]
The above works without making any changes to your classes. Since record values are final a new record much be created to replace the previous one using the accumulated sums.

Related

select more column not in group by using linq in c#

cmd = new SqlCommand(" ", con);
da = new SqlDataAdapter(cmd);
DataTable t_eight = new DataTable("t_eight");
da.Fill(t_eight); //databale "t_eight" fill
//linq query
var query3 = (from a in t_eight.AsEnumerable() //t_eigth Databale
group a by new
{ //Group by with condition
IdendityName = a.Field<String>("Idendity Name"),
ContactPersonName = a.Field<String>("Contact Person Name"),
CustomerName = a.Field<String>("Customer Name")
}
into g
select new
{
IdendinyName = g.Key.IdendityName,
ContactPersonName = g.Key.ContactPersonName,
CurtomerName = g.Key.CustomerName,
TotalBook = g.Sum(x => x.Field<Int32>("Total Book Quantity")
+ x.Field<Int32>("Quatan Book Qty")
- x.Field<Int32>("Return Book Quality"))
});
GridView1.DataSource = query3;
GridView1.DataBind();
Datatable contains columns Identity Name, customer Name, customer Contact Name, Total Book Quantity, Return Book Quality, and Quatan Book Qty.
Group by contains three column Identity Name, customer Name, and customer Contact Name
New column in select statement Total Book contains ( total book quant+Quatan Book Qty-Return Book Quality). I want all columns in the gridview but the grid contains Identity Name, customer Name, customer Contact Name, and total book columns
How can I do this?
Dataset table "t_eight"
Gridview missing column Quatan Book and Return Book
Assuming you expect the additional fields to be identical once the rows are grouped, you just need to pick a random row from the group to get the values - the First row should work.
var query3 = (from a in t_eight.AsEnumerable()//t_eigth Databale
group a by new
{//Group by with condition
IdendityName = a.Field<String>("Idendity Name"),
ContactPersonName = a.Field<String>("Contact Person Name"),
CustomerName = a.Field<String>("Customer Name")
}
into g
select new {
g.Key.IdendityName,
g.Key.ContactPersonName,
g.Key.CustomerName,
ReturnBookQuality = g.First().Field<Int32>("Return Book Quality"),
QuatanBookQty = g.First().Field<Int32>("Quatan Book Qty"),
TotalBook = g.Sum(x => x.Field<Int32>("Total Book Quantity")
+ x.Field<Int32>("Quatan Book Qty") - x.Field<Int32>("Return Book Quality"))
}
);
Note: I removed the redundant member names from the anonymous type, I don't see any reason to put them there.
If I understand you correctly, you want to see the totals of three columns besides the calculated TotalBook column. Here's how you can do that:
var query3 = (from a in t_eight.AsEnumerable()
group a by new
{
IdendityName = a.Field<String>("Idendity Name"),
ContactPersonName = a.Field<String>("Contact Person Name"),
CustomerName = a.Field<String>("Customer Name")
}
into g
let tbq = g.Sum(x => x.Field<Int32>("Total Book Quantity"))
let qbq = g.Sum(x => x.Field<Int32>("Quatan Book Qty"))
let rbq = g.Sum(x => x.Field<Int32>("Return Book Quality"))
select new
{
IdendinyName = g.Key.IdendityName,
ContactPersonName = g.Key.ContactPersonName,
CurtomerName = g.Key.CustomerName,
TotalBookQuantity = tbq,
QuatanBookQuantity = qbq,
ReturnBookQuantity = rbq,
TotalBook = tbq + qbq - rbq
});
The three let statements collect the individual sums per grouping, after which you can use the variables tbq etc. multiple times.

neo4j query to return node with collection item

I have some nodes in Neo4J database with array attribute. Something like:
Node (name = firstNode, array = [fist, second])
Node (name = secondNode, array = [second, third])
I want write query to return this combination:
name = firstNode, arrayItem = first
name = firstNode, arrayItem = second
name = secondNode, arrayItem = second
Name = secondNode, arrayItem = third
Anyone some suggestion?
UNWIND is for splitting up an array into multiple lines:
match (n:MyLabel)
unwind n.array as ele
return n.name, ele
(This assumes your nodes have a MyLabel label.)

Am trying to sort datatable dt, but its not working. Time Elapsed is my column name in dt. want to sort by DESC

public static DataTable resort(DataTable dt)
{
string sortByColumnsStr = "Time Elapsed DESC";
DataView dtview = new DataView(dt);
dtview.Sort = sortByColumnsStr;
DataTable dtsorted = dtview.ToTable();
return dtsorted;
}
Embed the column name with square brackets, like this:
string sortByColumnsStr = "[Time Elapsed] DESC";
You can eventually take a look at this: http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/1f37f760-b479-4b4a-a2db-0e828812ac0e/

Linq to Entity, selecting group with or without value

Hi Need some help with LINQ query.
I have entity called Shift. This entity has several value field but the ones I am intressted in are ShiftID (int), ShiftDate (DateTime) and GrossMount (decimal(10,2). And this needs to be grouped by month (binding this to a graph in ASP.NET).
I need data for the last 12 months grouped by month.
I have come a bit on the way with this post: Linq to Entity, selecting group without value but not quite all the way.
This is my code for now:
public IQueryable<Shift> GetPastMonths(int months, string accountNumber)
{
_context = new EtaxiEnteties();
var _date = DateTime.Today;
var _firstOfMonth = new DateTime(_date.Year, _date.Month, 31);
var _twelveMonthAgoFirstOfMonth = _firstOfMonth.AddMonths(-12);
// Generate a collection of the months and years for the last 12 months
var _monthYears = Enumerable.Range(-12, 12).Select(monthOffset => { var monthDate = _firstOfMonth.AddMonths(monthOffset); return new { y = monthDate.Year, m = monthDate.Month }; });
var _data = (from _monthYear in _monthYears
join _i in
(from _i in _context.Shifts.Where(acc => acc.Account.AccountNumber == accountNumber)
where _i.ShiftDate >= _twelveMonthAgoFirstOfMonth && _i.ShiftDate < _firstOfMonth
group _i by new { y = _i.ShiftDate.Year, m = _i.ShiftDate.Month } into g
select new { ShiftID = g.Key, GrossAmount = g.Count() }) on _monthYear equals _i.ShiftID into j
from _k in j.DefaultIfEmpty()
select new Shift() { ShiftDate = new DateTime(_monthYear.y, _monthYear.m, 1), GrossAmount = _k != null ? _k.GrossAmount : 0 });
return _data as IQueryable<Shift>;
}
Now I have in return a collection of Shift objects, grouped by month but still missing the GrossAmount. Althoug i would need this from today date (only getting from 1 of current month).
Believe this is my main problem: GrossAmount = g.Count(), but I am not sure
Any LINQ specialist out there that could give me a push?
Use GrossAmount = g.Sum(x => x.GrossAmount) to calculate total GrossAmount value of grouped Shift entities. I believe you have typo in GrossAmount (GrossMount) property name.

Lookup a field or Index for filter search?

I fetch have a large collection (35k+ - list of products)
for each item_cache in products_cache
list.Add(New Products With {
.product_id = item_cache.id,
.product_name = item_cache.name,
.moreHere = item_cache.moreHere,
.moreHere = item_cache.moreHere,
.moreHere = item_cache.moreHere,
.moreHere = item_cache.moreHere
})
next
return list.Tolist
The params we currently have are all in strings (home.aspx?p_name='Shirts').
After I have the list collection, is it better to search through string or search through index?
return list.where(function(c) c.product_name = 'Shirts')
Or should I retrieve first the index (PK) of the string
Dim p_id As Integer = dataGetIdOfProduct('Shirts')
return list.where(function(c) c.product_id = p_id)

Resources