mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DataFrame: more thorough detection of unsorted values (#51602)
This commit is contained in:
@@ -294,5 +294,19 @@ describe('align frames', () => {
|
||||
expect(isLikelyAscendingVector(new ArrayVector([7, 6, null]))).toBeFalsy();
|
||||
expect(isLikelyAscendingVector(new ArrayVector([7, 8, 6]))).toBeFalsy();
|
||||
});
|
||||
|
||||
it('ascending first/last', () => {
|
||||
expect(isLikelyAscendingVector(new ArrayVector([10, 20, 30, 5, 15, 7, 43, 29, 11]), 3)).toBeFalsy();
|
||||
expect(
|
||||
isLikelyAscendingVector(new ArrayVector([null, 10, 20, 30, 5, null, 15, 7, 43, 29, 11, null]), 3)
|
||||
).toBeFalsy();
|
||||
});
|
||||
|
||||
it('null stuffs', () => {
|
||||
expect(isLikelyAscendingVector(new ArrayVector([null, null, 1]), 3)).toBeTruthy();
|
||||
expect(isLikelyAscendingVector(new ArrayVector([1, null, null]), 3)).toBeTruthy();
|
||||
expect(isLikelyAscendingVector(new ArrayVector([null, null, null]), 3)).toBeTruthy();
|
||||
expect(isLikelyAscendingVector(new ArrayVector([null, 1, null]), 3)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -335,34 +335,46 @@ export function join(tables: AlignedData[], nullModes?: number[][]) {
|
||||
return data;
|
||||
}
|
||||
|
||||
// Quick test if the first and last points look to be ascending
|
||||
// Test a few samples to see if the values are ascending
|
||||
// Only exported for tests
|
||||
export function isLikelyAscendingVector(data: Vector): boolean {
|
||||
let first: any = undefined;
|
||||
export function isLikelyAscendingVector(data: Vector, samples = 50) {
|
||||
const len = data.length;
|
||||
|
||||
for (let idx = 0; idx < data.length; idx++) {
|
||||
const v = data.get(idx);
|
||||
if (v != null) {
|
||||
if (first != null) {
|
||||
if (first > v) {
|
||||
return false; // descending
|
||||
}
|
||||
break;
|
||||
}
|
||||
first = v;
|
||||
}
|
||||
// empty or single value
|
||||
if (len <= 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let idx = data.length - 1;
|
||||
while (idx >= 0) {
|
||||
const v = data.get(idx--);
|
||||
// skip leading & trailing nullish
|
||||
let firstIdx = 0;
|
||||
let lastIdx = len - 1;
|
||||
|
||||
while (firstIdx <= lastIdx && data.get(firstIdx) == null) {
|
||||
firstIdx++;
|
||||
}
|
||||
|
||||
while (lastIdx >= firstIdx && data.get(lastIdx) == null) {
|
||||
lastIdx--;
|
||||
}
|
||||
|
||||
// all nullish or one value surrounded by nullish
|
||||
if (lastIdx <= firstIdx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const stride = Math.max(1, Math.floor((lastIdx - firstIdx + 1) / samples));
|
||||
|
||||
for (let prevVal = data.get(firstIdx), i = firstIdx + stride; i <= lastIdx; i += stride) {
|
||||
const v = data.get(i);
|
||||
|
||||
if (v != null) {
|
||||
if (first > v) {
|
||||
if (v <= prevVal) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
prevVal = v;
|
||||
}
|
||||
}
|
||||
|
||||
return true; // only one non-null point
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user