The datagrouping in HighStock allows us to make an approximation of a unique value from a set of points.
The documentation says that some pre-built approximation function are available :
"average", "open", "high", "low", "close" and "sum"
we can easily imagine that 'average' returns the average of all the input values,
high take the highest, low, the lowest, sum makes the sum ( not sure what this one is for ?)
the question is, what the 'open' and 'close' approximation functions do ?
Basically, by looking at the source code, the "open" (resp. "close") approximation takes the first (resp. last) value from the array (if the group of values is non-empty):
open: function (arr) {
return arr.length ? arr[0] : (arr.hasNulls ? null : UNDEFINED);
},
...
close: function (arr) {
return arr.length ? arr[arr.length - 1] : (arr.hasNulls ? null : UNDEFINED);
},
...
Related
Assuming I have a List as below:
final numbers = [1, 0, -1, 1, -3, 0];
I'd like to generate another list where 1 results in true and 0 results in false and skip the others. So, in other words, I'd like a method like map where I can also skip some elements. In terms of test, it would assert to:
expect(newList, equals([true, false, true, false]));
In this result, I'd like to skip -1 and -3 in the list.
How can I achieve this?
Environment
Dart 2.18.5
Use the .where() method to get a new iterable with only the elements satisfying a predicate, then use .map() to apply the transformation on the result.
final numbers = [1, 0, -1, 1, -3, 0];
final result = numbers.where((n) => n == 1 || n == 0).map((n) => n == 1);
print(result);
\\ (true, false, true, false)
The most direct version would be:
var result = numbers.expand<bool>((n) =>
n == 0
? const <bool>[false]
: n == 1
? const <bool>[true]
: const <bool>[]);
The expand method can do everything map and where can, plus more,
Not particularly efficient, but not all bad either.
Another approach is to use a sync* function:
var result = () sync* {
for (var number in numbers) {
if (number == 0) {
yield false;
} else if (number == 1) {
yield true;
}
}();
If you don't care about creating a list eagerly, that's a also the approach for a list literal:
var result = [for (var number in numbers)
if (number == 0) false else if (number == 1) true
];
Or:
const _map = {0: [false], 1: [true]};
var result = [for (var number in numbers} ...?_map[number]];
The options are endless. In practice, doing where and map is probably more readable.
Ariel's answer gave me a better idea. In the example of the question, what we'd like to filter out are two values, which are 1 and 0. The real problem I'm dealing with right now is more complicated than this one, it has a wide range of lookup list. I haven't specifically asked "What is a more programmatic way to do this?" or "What if the lookup list has more values?".
So, if the values I'm looking for are more than these two values, a List of lookup values and contains method would be better for my case.
final numbers = [1, 0, -1, 1, -3, 0];
final lookup = {1, 0};
final result = numbers.where((n) => lookup.contains(n)).map((n) => n == 1 ? true : false).toList();
print(result);
This has some drawbacks though, some of which that come to my mind are:
Performance is definitely worse than Ariel's answer. My solution uses contains, which will perform look-ups in lookup rather than a simple byte-comparison with n == 1. So, it isn't great with large lists.
hashCode must be overriden for non-primitives. It is easy to compare int with an int in this simple example, but if you have an instance, you need to override hashCode, otherwise Dart will compare the memory addresses rather than values.
Using another collection type for lookup other than Set might also have performance impact because Set is inherently O(1) while the others might depend on their standard library implementation, but it's safe to assume they're going to be worse than Set. (See Ariel's comment).
BTW, lookup does not have to be a Set. I've done it Set because lookup contains distinct values and the order is not important.
Iterable.map is a 1:1 mapping; if your input has n elements, then the output must have n elements too.
Using numbers.where(...).map(...) works, but alternatively:
Use Iterable.map first to map either to desired values or to an invalid sentinel value. If your sentinel value is null, then you can use Iterable.whereType to filter out them out:
var transformed = numbers.map((n) {
switch (n) {
case 0:
return false;
case 1:
return true;
default:
return null;
}
}).whereType<bool>();
You might prefer this if you want all of your logic in a single callback.
Use collection-for instead of Iterable.map and collection-if instead of Iterable.where:
var transformed = [
for (var n in numbers)
if (isValidValue(n))
transform(n),
];
where you define isValidValue and transform functions with your filtering and transformation logic respectively.
I have 1M records in my db with such schema:
schema embeddings {
document embeddings {
field id type int {}
field text_embedding type tensor<double>(d0[960]) {
indexing: attribute | index
attribute {
distance-metric: euclidean
}
index {
hnsw {
max-links-per-node: 16
neighbors-to-explore-at-insert: 100
}
}
}
}
rank-profile closeness {
num-threads-per-search:1
inputs {
query(query_embedding) tensor<double>(d0[960])
}
first-phase {
expression: closeness(field, text_embedding)
}
}
}
My query for finding the nearest neighbors looks like this:
body = {
'yql': 'select * from embeddings where ({approximate:true, targetHits:100} nearestNeighbor(text_embedding, query_embedding));',
"hits":100,
'input': {
'query(query_embedding)': [...],
},
"ranking": {
"profile": "closeness",
"softtimeout": {
"enable": false
}
}
}
For some reasons, for certain vectors the number of results is smaller, than targetHits. Changing timeouts does not help.
Here is coverage section from the response:
"id": "toplevel",
"relevance": 1.0,
"fields": {
"totalCount": 39
},
"coverage": {
"coverage": 100,
"documents": 1000000,
"full": true,
"nodes": 1,
"results": 1,
"resultsFull": 1
},
Is there any way to receive exactly (or at least not less than) targetHits results (obviously there are enough results, since the closeness can be calculated for any other vector in the db)?
When you ask for targetHits:100, Vespa will expose that to the first-phase ranking phase, per content node. If it does not, then we would be very interested in how to reproduce. That is best done by creating a issue over at github vespa-engine/vespa. There is also support for dropping hits in first-phase ranking using rank-score-drop-limit, which can reduce the result set and totalCount. This does not seem to be enabled here.
The hits parameter (or limit in YQL) controls how many hits are returned in the response.
Vespa's default timeout is 500ms, and if your system is heavily overloaded (or using exact search with approximate:false), you might see soft-timeouts where Vespa returns a partial result. This situation is reflected in the returned result coverage element.
I do use tablesorter (https://mottie.github.io/tablesorter/docs/index.html)
To sort my HTML tables.
I have one sorting I cannot find howtoo. ie.
(4)
(dns)
1
2
3
5
dns
is to be sorted as:
1
2
3
(4)
5
(dns)
dns
in short: the () are to be ignored and numeric sort, numeric first then alphabetical.
I have seen how to replace characters, (doesn't work as "empty" as some rank too)
The parsers I have seen thusfar require me to create per header and known value to be replaced.
ie:
$.tablesorter.addParser({
id: 'nummeriek',
is: function(s) {
return false;
},
format: function(s) {
// format your data for normalization
return s.toLowerCase().replace('dns',999).replace('(dns)',999).replace('(4)',4);
},
type: 'numeric'
});
$('.tablesorter').tablesorter({
headers: {
6: {
sorter:'nummeriek'
}
}
});
If I have to do this for every possible table content I end up creating hundreds of replace() statements. as I have scores from 1 to 100 Thus (1) to (100) is possible too...
There must be an easier way. Any help is much appreciated.
The default digit parser "assumes" that numbers wrapped in parentheses are negative; this is a common method of indicating a negative number in accounting (ref).
To get around this, you will need to slightly modify the parser (demo)
$(function() {
$.tablesorter.addParser({
id: 'nummeriek',
is: function(s) {
return false;
},
format: function(str) {
// format your data for normalization
var s = str.replace(/[()]/g, ""),
n = parseFloat(s);
return !isNaN(n) && isFinite(n) ? n : s;
},
type: 'numeric'
});
$('.tablesorter').tablesorter({
headers: {
0: {
sorter: 'nummeriek'
}
}
});
});
Note: this parser always returns a non-numeric string without parentheses, e.g. "(dns)" will become "dns". I kept it this way so the "(dns)" entries will sort as if they are "dns".
Suppose I have documents with structure:
{
name:"some_name",
salary:INT_VAL,
date:YYYY.dd.MMTHH:mm:sssZ,
num_of_months:INT_VAL
}
And now I want to make a query to elastic, that would select top 10 documents that sorted by criteria salary*num_of_months.
How can I do this?
And what if I want to sort by criteria with some logic inside, sth. like
if (num_of_months < 5)
then criteria = salary*100 ;
elseif criteria = salary*200;
endif
sort_by_criteria()
Doing a Sort with a script will enable you to perform calculations on the data and return it in the right order:
GET /myindex/mytype/_search?pretty
{
"sort" :{
"_script" : {
"type" : "number",
"lang": "expression",
"script" : "doc['num_of_months'].value < 5 ? doc['salary']*100 : doc['salary']*200",
"order":"desc"
}
},
"size": 10
}
Note the use of the ternary operator to do the If statement.
With jQuery TableSorter, I can't filter a column correctly that contains European formatted digits (dot every 3 digit and comma as decimal sign). Anyway, sorting work like a charm.
See my problem here : http://jsfiddle.net/Ted22/9tBgZ/13/
I work with this piece of code :
jQuery.tablesorter.addParser({
id: "commaDigit",
is: function(s, table) {
var c = table.config;
return $.tablesorter.isDigit(s.replace(/[,.]/g, ""), c);
},
format: function(s) {
return $.tablesorter.formatFloat(s.replace(/[,.]/g, ""));
},
parsed: false,
type: "numeric"
});
Can you help me ?
Thanks in adavance !
Ted
Just set the usNumberFormat option to false (demo)