Rewrite mergeKeySets to be O(n) instead of O(n^3)
Ben Alpert committed
Jan 10, 2014 at 15:31 UTC
1efb14bcf6a5702febefdce5bcd34c70a44d5fce
1 file changed
+23
-26
src/addons/transitions/ReactTransitionKeySet.js
+23
-26
@@ -21,8 +21,6 @@
21
22
var ReactChildren = require('ReactChildren');
23
24
-var MERGE_KEY_SETS_TAIL_SENTINEL = {};
25
-
24
var ReactTransitionKeySet = {
25
/**
26
* Given `this.props.children`, return an object mapping key to child. Just
@@ -71,37 +69,36 @@ var ReactTransitionKeySet = {
69
prev = prev || {};
70
next = next || {};
71
74
- var keySet = {};
75
- var prevKeys = Object.keys(prev).concat([MERGE_KEY_SETS_TAIL_SENTINEL]);
76
- var nextKeys = Object.keys(next).concat([MERGE_KEY_SETS_TAIL_SENTINEL]);
77
- var i;
78
- for (i = 0; i < prevKeys.length - 1; i++) {
79
- var prevKey = prevKeys[i];
72
+ // For each key of `next`, the list of keys to insert before that key in
73
+ // the combined list
74
+ var nextKeysPending = {};
75
+
76
+ var pendingKeys = [];
77
+ for (var prevKey in prev) {
78
if (next[prevKey]) {
81
- continue;
79
+ if (pendingKeys.length) {
80
+ nextKeysPending[prevKey] = pendingKeys;
81
+ pendingKeys = [];
82
+ }
83
+ } else {
84
+ pendingKeys.push(prevKey);
85
}
86
+ }
87
84
- // This key is not in the new set. Place it in our
85
- // best guess where it should go. We do this by searching
86
- // for a key after the current one in prevKeys that is
87
- // still in nextKeys, and inserting right before it.
88
- // I know this is O(n^2), but this is not a particularly
89
- // hot code path.
90
- var insertPos = -1;
91
-
92
- for (var j = i + 1; j < prevKeys.length; j++) {
93
- insertPos = nextKeys.indexOf(prevKeys[j]);
94
- if (insertPos >= 0) {
95
- break;
88
+ var i;
89
+ var keySet = {};
90
+ for (var nextKey in next) {
91
+ if (nextKeysPending[nextKey]) {
92
+ for (i = 0; i < nextKeysPending[nextKey].length; i++) {
93
+ keySet[nextKeysPending[nextKey][i]] = true;
94
}
95
}
98
-
99
- // Insert before insertPos
100
- nextKeys.splice(insertPos, 0, prevKey);
96
+ keySet[nextKey] = true;
97
}
98
103
- for (i = 0; i < nextKeys.length - 1; i++) {
104
- keySet[nextKeys[i]] = true;
99
+ // Finally, add the keys which didn't appear before any key in `next`
100
+ for (i = 0; i < pendingKeys.length; i++) {
101
+ keySet[pendingKeys[i]] = true;
102
}
103
104
return keySet;