Linq operator to aggregate matching value and weight them - linq

Working code.
double[] confirmingList = new double[] { -3, -2, -1 };
var Tdb = rDatas
.Select(d => new
{
TScore = (new List<double> {
d.T15Min, // Let this count .2
d.T30Min, // .25
d.T65Min, // .3
d.T130Min, // .4
d.T195Min, // .5
d.TDaily, // .8
d.TWeekly // 1
}).Count(c => confirmingList.Contains(c))
What I want is to aggregate by time frame match and weighting by property. Is there some Linq Kung Fu that does that? Should I have some class that I pass to multiply weighting by property name? I suspect there is something in the aggregate operator that would allow for this?
Can't really find something that shows a logical operation match while aggregating values with a modification or weighting.

Using the indexed Select method, you can match each timeframe to its weight when it should be counted:
double[] confirmingList = new double[] { -3, -2, -1 };
var weights = new[] { 0.2, 0.25, 0.3, 0.4, 0.5, 0.8, 1.0 };
var Tdb = rDatas
.Select(d => new {
TScore = (new[] {
d.T15Min, // Let this count .2
d.T30Min, // .25
d.T65Min, // .3
d.T130Min, // .4
d.T195Min, // .5
d.TDaily, // .8
d.TWeekly // 1
}).Select((t,i) => confirmingList.Contains(t) ? weights[i] : 0).Sum()
});

Related

get an array of doubles from a an array within a custom object in a map

I have a custom object (Allocation) in a Map. I am looking to get the column of weights for each Allocation entry in the map. For example if I have 10 Map entries and each Allocation object has 3 weights, I would like to get the ith weight of each Map entry in Java 8. Here is an example of what I am looking for. Any ideas or suggestions to do this in Java 8. Thank you!
key: portfolio1, Object: (risk=0.03, weights={0.3,0.2,0.5}, returnvalue=0.5)
Key: portfolio2, Object: (risk=0.05, weights={0.4,0.4,0.2}, returnvalue=0.3)
Key: portfolio3, Object: (risk=0.01, weights={0.5, 0.25, 0.25}, return=0.6)
if the above 3 Portfolios are 3 Map entries, I would like to get the weights from each of the 3 Portfolios in an array as:
first column of weights as
weight[0]=0.3 from portfolio 1
weight[1] = 0.4 from portfolio 2
weight[2] = 0.5 from portfolio 3
second column of weights as:
weight[0] = 0.2 from portfolio 1
weight[1] = 0.4 from portfolio 2
weight[2] = 0.25 from portfolio 3
public class Allocation {
private double returnValue;
private double risk;
private double[] weights;
public Allocation() {
returnValue = 0;
risk = 0;
weights = null;
}
public double getReturnValue() {
return returnValue;
}
public void setReturnValue(double returnValue) {
this.returnValue = returnValue;
}
public double getRisk() {
return risk;
}
public void setRisk(double risk) {
this.risk = risk;
}
public double[] getWeights() {
return weights;
}
public void setWeights(double[] weights) {
this.weights = weights;
}
}
Map<String, Allocation> map = new LinkedHashMap<>();
map.put("portfolio1", a1);
map.put("portfolio2", a2);
map.put("portfolio3", a3);
// Calculate max size of the weights array. Can be omitted if you already know the size.
int maxNumberOfWeights = map.values()
.stream()
.mapToInt(allocation -> allocation.getWeights().length)
.max()
.getAsInt();
// List of list of columns
List<List<Double>> result = IntStream.range(0, maxNumberOfWeights)
.mapToObj(idx -> map.values()
.stream()
.map(Allocation::getWeights)
.map(doubles -> doubles.length > idx ? doubles[idx] : 0) // can be just .map(doubles -> doubles[idx]) if the length of all weights arrays will always be the same
.collect(Collectors.toList()))
.collect(Collectors.toList());
System.out.println(result);
Output
[[0.3, 0.4, 0.5], [0.2, 0.4, 0.25], [0.5, 0.2, 0.25]]
Or to have double[]s instead, you can do:
List<double[]> result = IntStream.range(0, maxNumberOfWeights)
.mapToObj(idx -> map.values()
.stream()
.map(Allocation::getWeights)
.mapToDouble(doubles -> doubles.length > idx ? doubles[idx] : 0)
.toArray())
.collect(Collectors.toList());
result.forEach(doubles -> System.out.println(Arrays.toString(doubles)));
Output
[0.3, 0.4, 0.5]
[0.2, 0.4, 0.25]
[0.5, 0.2, 0.25]
Create a new function in your class
public double getWeightByIndex(int i){
return weights[i];
}
Now say you have an arraylist of Portfolios and presumably all of them have the same column length then
ArrayList<double[]> result = new ArrayList<double[]>();
for(int i=0; i<allocationList[0].length; i++){//for each column
double arr[] = new double[allocationList[0].length];
for(Allocation a : allocationList){
arr[i] = a.get(i).getWeightByIndex(i)
}
result.add(arr);
}
At the end of it you should have an arraylist of array by corresponding index.
I used an arraylist because i do not know your object definition but it will produce the output you require
i.e. weight = result.get(1) will produce
weight[0] = 0.3
weight[1] = 0.4
weight[2] = 0.5

Is adding the new data point not at the end of array a bad idea?

This involves a design decision. An interviewer asked me to write something to plot the data assuming there are 100 data points, and new data point comes in (and given to the program) every 0.1, 0.3 or 0.5 or 1 second. (it can change in the future, and I think the smallest granularity on a common web browser is 0.03 seconds).
I proceeded to think about adding the new data point to the Nth position in the array. For example, adding the data at array entry 36, and plot the data from 37th to 99th, and then from 0th to 36th. Next time, add the data at array entry 37, and plot the data from 38th to 99th, and then from 0th to 37th.
This way, we don't need to "unshift" (shift out) the data at entry 0 and therefore needing to shift entry 1 to 99 one place forward, and then add the new data point at entry 99, and then plot data entry 0 to 99.
For some reason, the interviewer gave a big frown, and said, "why would we do that? It is not heavy to shift 99 data over." I said what if there are 500 or 1000 data point we'd like to plot in the future, we might want to avoid shifting data about 500 times or 1000 time each time when a new data point comes in.
He mentioned "let's say we just shift them anyway".
Is shifting the data actually not an issue or concern? What if on the screen we have 10 or 15 of such widgets, apps, or webpages, to monitor 15 types of data, we might want to avoid shifting 15,000 data entries constantly.
I naively tried to load n canvas to the page, and compared the time needed to plot against the time taken shifting array.
tldr: Whichever method is used to shift the points, the method is negligible against the time needed to plot the points. (~ 3%)
I only run the code in ff70 with casual js.
(For instance I am stocking an array of objects even though optimization may be available if I stock only floats)
There are two kind of measures: push and refresh.
push measures the time needed to shift a point and add a new one
refresh measures the time needed to replot the canvas
Below three approaches for pushing: either push (Array.prototype.(shift|push), tail to a queue (and move the head), or nopole's approach
Every 10ms I plot the time spent in the push method. On top of the picture, the cumulative time spent. I stop once a run has reached 100 points and reload the page for another run.
The y axis is the same accross all runs
Push
push avg: (838+886+864)/3 = 862ms
Queue
push avg: (625+760+825)/3 = 736ms
refresh avg: (40554+39934+40915+39194+39264+30480)/6 = 38390ms
Nopole
push avg: (792+861+871)/3 = 841ms
Notice that for one sample: (625/30480) we seem to have benefited from some cpu willing to work. So the shifting method feels even more irrelevant.
It is hard to tell which approach is better, because of the few samples drought for each kind of methods and it is likely more an issue of cpu's overall workload rather than the page itself
To reproduce
let timerPush = 0
let timerRefresh = 0
class Canvas {
constructor (f, el, period) {
this.w = 300
this.h = 300
this.points = []
const canvas = document.createElement('canvas')
canvas.style.cssText = 'background:#eeeeee; margin:10px;'
canvas.width = this.w
canvas.height = this.h
this.ctx = canvas.getContext('2d')
this.ctx.transform(1, 0, 0, -1, 0, this.h / 2)
this.ctx.lineWidth = 1
this.dw = this.w / this.MAX_POINTS
this.dh = this.h / 2
el.appendChild(canvas)
let x = 0
this.timer = setInterval(_ => {
x += period
this.push({ x, y: f(x) })
this.refresh()
}, period * 1000)
}
refresh () {
const now = performance.now()
this.ctx.clearRect(0, -this.h / 2, this.w, this.h)
this.ctx.beginPath()
this._plot()
this.ctx.stroke()
this.ctx.closePath()
timerRefresh += performance.now() - now
}
push (p) {
const now = performance.now()
this._push(p)
timerPush += performance.now() - now
}
_plot () {
if (!this.points.length) { return }
this.ctx.moveTo(0 * this.dw, this.points[0].y * this.dh)
for (let i = 1; i < this.points.length; ++i) {
const p = this.points[i]
this.ctx.lineTo(i * this.dw, p.y * this.dh)
}
}
_push (p) {
if (this.points.length == this.MAX_POINTS) {
this.points.shift()
}
this.points.push(p)
}
MAX_POINTS = 100
}
class CanvasQueue extends Canvas {
constructor () {
super(...arguments)
this.tail = {}
this.head = this.tail
this.n = 0
}
_plot () {
if (!this.head.next.p) return
let node = this.head.next
this.ctx.moveTo(0 * this.dw, node.p.y * this.dh)
let i = 1
node = node.next
while (node) {
this.ctx.lineTo(i * this.dw, node.p.y * this.dh)
++i
node = node.next
}
}
_push (p) {
if (this.n === this.MAX_POINTS) {
this.head = this.head.next
} else {
this.n++
}
const node = { p }
this.tail.next = node
this.tail = node
}
}
class CanvasNopole extends Canvas {
constructor () {
super(...arguments)
this.start = 0
}
_plot () {
if (!this.points.length) { return }
const s = this.start
let z = 1
let startBack = 0
if (this.points[s]){
this.ctx.moveTo(0 * this.dw, this.points[s].y * this.dh)
for (let i = s+1; i < this.points.length; ++i) {
const p = this.points[i]
this.ctx.lineTo(z++ * this.dw, p.y * this.dh)
}
}else{
this.ctx.moveTo(0 * this.dw, this.points[0].y * this.dh)
startBack = 1
}
for (let i = startBack; i < s; ++i) {
const p = this.points[i]
this.ctx.lineTo(z++ * this.dw, p.y * this.dh)
}
}
_push (p) {
this.points[this.start] = p
this.start = (this.start + 1) % this.MAX_POINTS
}
}
class CanvasSummary extends Canvas {
constructor () {
super(...arguments)
this.ctx.resetTransform()
this.ctx.transform(1, 0, 0, -1, 0, this.h)
// we know beforehand that timer should not grow bigger
const deltaTimer = 50
this.dh = this.h / deltaTimer
this.old = timerPush
}
refresh () {
this.ctx.clearRect(0, 0, this.w, this.h)
this.ctx.beginPath()
this.ctx.resetTransform()
this.ctx.fillText(`push: ${timerPush} plot: ${timerRefresh}`, 5, 20)
this.ctx.transform(1, 0, 0, -1, 0, this.h)
this._plot()
this.ctx.stroke()
this.ctx.closePath()
}
push (p) {
this._push(p)
}
}
function run () {
const $summary = document.querySelector('.summary')
const $bench = document.querySelector('.bench')
const cs = new CanvasSummary(x => {
if (cs.points.length === cs.MAX_POINTS) {
clearInterval(cs.timer)
}
const y = timerPush - cs.old
cs.old = timerPush
return y
}, $summary, 1)
//const canvas = Array(30).fill(0).map(x => new Canvas(Math.sin, $bench, 0.01))
//const canvas = Array(30).fill(0).map(x => new CanvasQueue(Math.sin, $bench, 0.01))
const canvas = Array(30).fill(0).map(x => new CanvasNopole(Math.sin, $bench, 0.01))
}
run()
<section class="summary"></section>
<hr/>
<div class="bench"></div>

Animation doesn't show steps-in-between

I have created a simple function that would "animate" the cell backcolor at a tap, it works perfectly fine:
Color nOldColor = _grid.BackgroundColor;
for (int i = 0; i <= 100; i += 5)
{
double f = (double)i / (double)100;
Color nNewColor = PCLHelper.BlendColors(nOldColor, Color.Red, f);
_grid.BackgroundColor = nNewColor;
_label1.BackgroundColor = nNewColor;
await Task.Delay(5);
}
_grid.BackgroundColor = nOldColor;
_label1.BackgroundColor = nOldColor;
Now I wanted to do the same with an Animation, but the animation doesn't show the steps "in-between" but rather (as it looks to me) switches to the final color:
private async void animateButtonTouched()
{
int repeatCountMax = 100;
Color nOldColor = _grid.BackgroundColor;
var repeatCount = 0;
_grid.Animate("changeBG", new Animation((val) =>
{
double f = (double)repeatCount / (double)100;
Color nNewColor = PCLHelper.BlendColors(nOldColor, Color.Red, f);
_grid.BackgroundColor = nNewColor;
_label1.BackgroundColor = nNewColor;
}),
5, //duration. I've also tried it with 100. Nothing helped
finished: (val, b) =>
{
repeatCount++;
}, repeat: () =>
{
return repeatCount < repeatCountMax;
});
What am I doing wrong?
"You are making it more difficult than it needs to be." Trademark pending 🍣
The Animate callback is providing the stepping value (or keyframe value). This is a double from 0 to 1 that is called ever X milliseconds (i.e. the length of a single animation frame, 16 default) over the course of X milliseconds (250 default).
So in this example the ShiftToColor gets called 125 times (2000 / 16) with a value that is evenly divided from 0 to 1, thus steps of .008.
var orgColor = aFormsElementInstance.BackgroundColor;
aFormsElementInstance.Animate("changeBG", new Animation((val) =>
{
Color ShiftToColor(Color From, Color To, double pct)
{
var r = From.R + ((To.R - From.R) * val);
var g = From.G + ((To.G - From.G) * val);
var b = From.B + ((To.B - From.B) * val);
return new Color(r, g, b);
}
Device.BeginInvokeOnMainThread(() =>
{
aFormsElementInstance.BackgroundColor = ShiftToColor(orgColor, Color.Red, val);
});
}), 16, 2000);
Results in:

3D Boolean operations with Three CSG

Following the example here:
http://learningthreejs.com/blog/2011/12/10/constructive-solid-geometry-with-csg-js/
And using Three.js with https://github.com/chandlerprall/ThreeCSG, I'm trying to do 3D boolean operations on nodes from the model. Like for example if I have a wall with a window, I want to do invert() on that to get just the window.
I have a function that returns all the vertices of the polygons of a node, here's an example of vertices of an object without holes https://pastebin.com/8dhYzPwE.
I'm using ThreeCSG like this:
const geometryThree = new THREE.Geometry();
geometryThree.vertices.push(
...vertices
);
const geometryCsg = new ThreeBSP(geometryThree);
But that's what I'm getting in geometryCsg:
"{
"matrix": {
"elements": {
"0": 1,
"1": 0,
"2": 0,
"3": 0,
"4": 0,
"5": 1,
"6": 0,
"7": 0,
"8": 0,
"9": 0,
"10": 1,
"11": 0,
"12": 0,
"13": 0,
"14": 0,
"15": 1
}
},
"tree": {
"polygons": []
}
}"
I think it's because the geometry.faces.length is 0.
How can I make the vertices array to be a proper Three.Geometry such that the faces won't be empty? Geometry.elementsNeedsUpdate doesn't work...
Is there an example that uses polygons of a shape as an array of Vector3s and transforms that to csg?
I just worked on a demo using THREE csg: the Viewer meshes have an indexed array of vertices so you cannot create a BSP directly out of it. Also my code is using a web worker to process the meshes in order to keep the UI responsive with large models, so I need first to send the mesh data to the worker and reconstruct a simple THREE.Mesh on the worker side, the code looks like below:
// Sends component geometry to the web worker
postComponent (dbId) {
const geometry = this.getComponentGeometry(dbId)
const msg = {
boundingBox: this.getComponentBoundingBox(dbId),
matrixWorld: geometry.matrixWorld,
nbMeshes: geometry.meshes.length,
msgId: 'MSG_ID_COMPONENT',
dbId
}
geometry.meshes.forEach((mesh, idx) => {
msg['positions' + idx] = mesh.positions
msg['indices' + idx] = mesh.indices
msg['stride' + idx] = mesh.stride
})
this.worker.postMessage(msg)
}
// get geometry for all fragments in a component
getComponentGeometry (dbId) {
const fragIds = Toolkit.getLeafFragIds(
this.viewer.model, dbId)
let matrixWorld = null
const meshes = fragIds.map((fragId) => {
const renderProxy = this.viewer.impl.getRenderProxy(
this.viewer.model,
fragId)
const geometry = renderProxy.geometry
const attributes = geometry.attributes
const positions = geometry.vb
? geometry.vb
: attributes.position.array
const indices = attributes.index.array || geometry.ib
const stride = geometry.vb ? geometry.vbstride : 3
const offsets = geometry.offsets
matrixWorld = matrixWorld ||
renderProxy.matrixWorld.elements
return {
positions,
indices,
offsets,
stride
}
})
return {
matrixWorld,
meshes
}
}
// On the worker side reconstruct THREE.Mesh
// from received data and create ThreeBSP
function buildComponentMesh (data) {
const vertexArray = []
for (let idx=0; idx < data.nbMeshes; ++idx) {
const meshData = {
positions: data['positions' + idx],
indices: data['indices' + idx],
stride: data['stride' + idx]
}
getMeshGeometry (meshData, vertexArray)
}
const geometry = new THREE.Geometry()
for (var i = 0; i < vertexArray.length; i += 3) {
geometry.vertices.push(vertexArray[i])
geometry.vertices.push(vertexArray[i + 1])
geometry.vertices.push(vertexArray[i + 2])
const face = new THREE.Face3(i, i + 1, i + 2)
geometry.faces.push(face)
}
const matrixWorld = new THREE.Matrix4()
matrixWorld.fromArray(data.matrixWorld)
const mesh = new THREE.Mesh(geometry)
mesh.applyMatrix(matrixWorld)
mesh.boundingBox = data.boundingBox
mesh.bsp = new ThreeBSP(mesh)
mesh.dbId = data.dbId
return mesh
}
function getMeshGeometry (data, vertexArray) {
const offsets = [{
count: data.indices.length,
index: 0,
start: 0}
]
for (var oi = 0, ol = offsets.length; oi < ol; ++oi) {
var start = offsets[oi].start
var count = offsets[oi].count
var index = offsets[oi].index
for (var i = start, il = start + count; i < il; i += 3) {
const a = index + data.indices[i]
const b = index + data.indices[i + 1]
const c = index + data.indices[i + 2]
const vA = new THREE.Vector3()
const vB = new THREE.Vector3()
const vC = new THREE.Vector3()
vA.fromArray(data.positions, a * data.stride)
vB.fromArray(data.positions, b * data.stride)
vC.fromArray(data.positions, c * data.stride)
vertexArray.push(vA)
vertexArray.push(vB)
vertexArray.push(vC)
}
}
}
The complete code of my sample is there: Wall Analyzer and the live demo there.

How to get the Max() of a Count() with LINQ

I'm new to LINQ and I have this situation. I have this table:
ID Date Range
1 10/10/10 9-10
2 10/10/10 9-10
3 10/10/10 9-10
4 10/10/10 8-9
5 10/11/10 1-2
6 10/11/10 1-2
7 10/12/10 5-6
I just want to list the Maximun of rows per date by range, like this:
Date Range Total
10/10/10 9-10 3
10/11/10 1-2 2
10/12/10 5-6 1
I want to do this by using LINQ, do you have any ideas of how to do this?
I think something along these lines should work:
List<MyTable> items = GetItems();
var orderedByMax = from i in items
group i by i.Date into g
let q = g.GroupBy(i => i.Range)
.Select(g2 => new {Range = g2.Key, Count = g2.Count()})
.OrderByDescending(i => i.Count)
let max = q.FirstOrDefault()
select new {
Date = g.Key,
Range = max.Range,
Total = max.Count
};
Using extension methods:
List<MyTable> items = GetItems();
var rangeTotals = items.GroupBy(x => new { x.Date, x.Range }) // Group by Date + Range
.Select(g => new {
Date = g.Key.Date,
Range = g.Key.Range,
Total = g.Count() // Count total of identical ranges per date
});
var rangeMaxTotals = rangeTotals.Where(rt => !rangeTotals.Any(z => z.Date == rt.Date && z.Total > rt.Total)); // Get maximum totals for each date
unfortunately I can't test this at the moment but give this a try:
List<MyTable> items = GetItems();
items.Max(t=>t.Range.Distinct().Count());
This approach:
1) Groups by Date
2) For each Date, groups by Range and calculates the Total
3) For each Date, selects the item with the greatest Total
4) You end up with your result
public sealed class Program
{
public static void Main(string[] args)
{
var items = new[]
{
new { ID = 1, Date = new DateTime(10, 10, 10), Range = "9-10" },
new { ID = 2, Date = new DateTime(10, 10, 10), Range = "9-10" },
new { ID = 3, Date = new DateTime(10, 10, 10), Range = "9-10" },
new { ID = 4, Date = new DateTime(10, 10, 10), Range = "8-9" },
new { ID = 5, Date = new DateTime(10, 10, 11), Range = "1-2" },
new { ID = 6, Date = new DateTime(10, 10, 11), Range = "1-2" },
new { ID = 7, Date = new DateTime(10, 10, 12), Range = "5-6" },
};
var itemsWithTotals = items
.GroupBy(item => item.Date) // Group by Date.
.Select(groupByDate => groupByDate
.GroupBy(item => item.Range) // Group by Range.
.Select(groupByRange => new
{
Date = groupByDate.Key,
Range = groupByRange.Key,
Total = groupByRange.Count()
}) // Got the totals for each grouping.
.MaxElement(item => item.Total)); // For each Date, grab the item (grouped by Range) with the greatest Total.
foreach (var item in itemsWithTotals)
Console.WriteLine("{0} {1} {2}", item.Date.ToShortDateString(), item.Range, item.Total);
Console.Read();
}
}
/// <summary>
/// From the book LINQ in Action, Listing 5.35.
/// </summary>
static class ExtensionMethods
{
public static TElement MaxElement<TElement, TData>(this IEnumerable<TElement> source, Func<TElement, TData> selector) where TData : IComparable<TData>
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
bool firstElement = true;
TElement result = default(TElement);
TData maxValue = default(TData);
foreach (TElement element in source)
{
var candidate = selector(element);
if (firstElement || (candidate.CompareTo(maxValue) > 0))
{
firstElement = false;
maxValue = candidate;
result = element;
}
}
return result;
}
}
According to LINQ in Action (Chapter 5.3.3 - Will LINQ to Objects hurt the performance of my code?), using the MaxElement extension method is one of the most effecient approaches. I think the performance would be O(4n); one for the first GroupBy, two for the second GroupBy, three for the Count(), and four for loop within MaxElement.
DrDro's approach is going to be more like O(n^2) since it loops the entire list for each item in the list.
StriplingWarrior's approach is going to be closer to O(n log n) because it sorts the items. Though I'll admit, there may be some crazy magic in there that I don't understand.

Resources