Skip to content

Commit 7e0ff7f

Browse files
committed
fix helpers.getIndex
1 parent dfe8166 commit 7e0ff7f

File tree

4 files changed

+140
-65
lines changed

4 files changed

+140
-65
lines changed

can-query-logic-test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require("./src/set-test");
2+
require("./src/helpers-test");
23
require("./src/types/make-real-number-range-inclusive-test");
34
require("./src/types/comparisons-test");
45
require("./src/types/and-or-not-test");

src/helpers-test.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
var QUnit = require("steal-qunit");
2+
var helpers = require("./helpers");
3+
var canReflect = require("can-reflect");
4+
5+
QUnit.module("can-query-logic/helpers");
6+
7+
8+
QUnit.test('.getIdentityIndex', function(){
9+
var items = [
10+
{id: 1, name: "Item 0"},
11+
{id: 2, name: "Item 1"},
12+
{id: 3, name: "Item 1"},
13+
{id: 4, name: "Item 1"},
14+
{id: 5, name: "Item 2"}
15+
];
16+
17+
canReflect.eachIndex(items, function(item) {
18+
canReflect.assignSymbols(item, {
19+
"can.getSchema": function() {
20+
return {
21+
type: "map",
22+
identity: ["id"],
23+
keys: {
24+
id: Number,
25+
name: String
26+
}
27+
};
28+
}
29+
});
30+
});
31+
32+
var props = {id:2, name: "Item 1"};
33+
canReflect.assignSymbols(props,{
34+
"can.getSchema": function() {
35+
return {
36+
type: "map",
37+
identity: ["id"],
38+
keys: {
39+
id: Number,
40+
name: String
41+
}
42+
};
43+
}
44+
});
45+
var compare = helpers.sorter("name", {});
46+
var res = helpers.getIdentityIndex(compare, items, props, 1);
47+
QUnit.deepEqual(res, 1);
48+
});
49+
50+
QUnit.test(".getIndex should not sort unchanged items #33", function() {
51+
52+
var items = [
53+
{id: 1, name: "Item 0"},
54+
{id: 2, name: "Item 1"},
55+
{id: 3, name: "Item 1"},
56+
{id: 4, name: "Item 1"},
57+
{id: 5, name: "Item 2"}
58+
];
59+
60+
canReflect.eachIndex(items, function(item) {
61+
canReflect.assignSymbols(item, {
62+
"can.getSchema": function() {
63+
return {
64+
type: "map",
65+
identity: ["id"],
66+
keys: {
67+
id: Number,
68+
name: String
69+
}
70+
};
71+
}
72+
});
73+
});
74+
75+
var compare = helpers.sorter("name", {});
76+
77+
var res1 = helpers.getIndex(compare,items, items[0]);
78+
var res2 = helpers.getIndex(compare,items, items[1]);
79+
var res3 = helpers.getIndex(compare,items, items[2]);
80+
var res4 = helpers.getIndex(compare,items, items[3]);
81+
82+
83+
QUnit.equal(res1, 0);
84+
QUnit.equal(res2, 1);
85+
QUnit.equal(res3, 2);
86+
QUnit.equal(res4, 3);
87+
});

src/helpers.js

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,56 @@ var helpers = {
4949
}
5050
});
5151
},
52+
// Get the index of an item by it's identity
53+
// Starting from the middle of the items
54+
// return the index of match in the right direction
55+
// or in the left direction
56+
// otherwise return the last index
57+
// see getIdentityIndexByDirection
58+
getIdentityIndex: function(compare, items, props, startIndex) {
59+
var identity = canReflect.getIdentity(props),
60+
starterItem = items[startIndex];
61+
// check if the middle has a match
62+
if (compare(props, starterItem) === 0) {
63+
if (identity === canReflect.getIdentity(starterItem)) {
64+
return startIndex;
65+
}
66+
}
67+
68+
var rightResult = this.getIdentityIndexByDirection(compare, items, props, startIndex+1, 1),
69+
leftResult;
70+
if(rightResult.index) {
71+
return rightResult.index;
72+
} else {
73+
leftResult = this.getIdentityIndexByDirection(compare, items, props, startIndex-1, -1);
74+
}
75+
if(leftResult.index !== undefined) {
76+
return leftResult.index;
77+
}
78+
// put at the last index item that doesn't match an identity
79+
return rightResult.lastIndex;
80+
},
81+
// Get the index of an item by it's identity
82+
// for a given direction (right or left)
83+
// 1 for right
84+
// -1 for left
85+
getIdentityIndexByDirection: function(compare, items, props, startIndex, direction) {
86+
var currentIndex = startIndex;
87+
var identity = canReflect.getIdentity(props);
88+
while(currentIndex >= 0 && currentIndex < items.length) {
89+
var currentItem = items[currentIndex];
90+
var computed = compare(props, currentItem);
91+
if(computed === 0) {
92+
if( identity === canReflect.getIdentity(currentItem)) {
93+
return {index: currentIndex};
94+
}
95+
} else {
96+
return {lastIndex: currentIndex - direction};
97+
}
98+
currentIndex = currentIndex + direction;
99+
}
100+
return {lastIndex: currentIndex - direction};
101+
},
52102
//
53103
getIndex: function(compare, items, props) {
54104
if (!items || !items.length) {
@@ -62,36 +112,22 @@ var helpers = {
62112
}
63113

64114
var low = 0,
65-
high = items.length,
66-
range = [];
115+
high = items.length;
67116

68117
// From lodash lodash 4.6.1 <https://lodash.com/>
69118
// Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
70119
while (low < high) {
71120
var mid = (low + high) >>> 1,
72121
item = items[mid],
73122
computed = compare(props, item);
74-
75123
if (computed === 0) {
76-
range.push(item);
77-
low = mid + 1;
78-
high--;
124+
return this.getIdentityIndex(compare, items, props, mid);
79125
} else if (computed === -1) {
80126
high = mid;
81127
} else {
82128
low = mid + 1;
83129
}
84130
}
85-
if (range.length > 0) {
86-
for (var i = 0; i < range.length; i++) {
87-
var itemInRange = range[i],
88-
id = canReflect.getSchema(itemInRange).identity[0];
89-
if (canReflect.hasOwnKey(props, id) && props[id] === itemInRange[id]) {
90-
high = items.indexOf(itemInRange);
91-
break;
92-
}
93-
}
94-
}
95131
return high;
96132
// bisect by calling sortFunc
97133
},

src/types/basic-query-sorting-test.js

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -356,52 +356,3 @@ QUnit.test("index uses can-reflect", function(){
356356
QUnit.deepEqual([obj1Read, obj2Read, itemKeyRead, itemOwnKeyRead],
357357
[true, true, true, true], "read everything");
358358
});
359-
360-
361-
QUnit.test("index should not sort unchanged items #33", function(assert) {
362-
canReflect.assignSymbols({},{
363-
"can.getSchema": function() {
364-
return {
365-
type: "map",
366-
identity: ["id"],
367-
keys: {
368-
id: Number,
369-
name: String
370-
}
371-
};
372-
}
373-
});
374-
375-
var items = [
376-
{id: 1, name: "Item 0"},
377-
{id: 2, name: "Item 1"},
378-
{id: 3, name: "Item 1"},
379-
{id: 4, name: "Item 1"},
380-
{id: 5, name: "Item 2"}
381-
];
382-
383-
canReflect.eachIndex(items, function(item, i) {
384-
canReflect.assignSymbols(item, {
385-
"can.getSchema": function() {
386-
return {
387-
type: "map",
388-
identity: ["id"],
389-
keys: {
390-
id: Number,
391-
name: String
392-
}
393-
};
394-
}
395-
});
396-
});
397-
398-
399-
400-
var query = new BasicQuery({
401-
sort: "name"
402-
});
403-
404-
var res = query.index({id:4, name: "Item 1"}, items);
405-
406-
QUnit.equal(res, 3);
407-
});

0 commit comments

Comments
 (0)