我正在使用Map来匹配传入的请求。我希望在得到它们后立即将这些请求与他们的对匹配。订单很重要,因为它是第一个来,首先匹配。避免不必要的操作是必需的。我的理解是哈希映射比数组迭代更快,而映射维护顺序。匹配流对象的最佳实现是什么,几乎没有空间或时间复杂度?数据结构不是一成不变的,只要信息不丢失,它就可以以任何优化的格式进行修改和编码。根据我的理解,可以实现的最好的是O(n)。我面临的另一个问题是散列是覆盖队列中的重复项。这就是我所拥有的。
function* match(items, identity, remaining = new Map()) {
for (let item of items) {
let id = identity(item);
let pair = x =>({type:x.type==="passenger"? "driver": "passenger", direction:x.direction, time:x.time})
let key = item=> item.type + item.direction + item.time;
let candidate = remaining.get(key(pair(id)));
if (candidate) {
remaining.delete(key(pair(id)));
yield [item, candidate];
} else {
remaining.set(key(id), item);
}
}
}
// Example:
let items = [{
type: 'driver',
direction: 'east',
time: '9:15',
name:['Archibald Trump']
},{
type: 'passenger',
direction: 'east',
time: '9:15',
name:['Bacon Eater']
},{
type: 'passenger',
direction: 'east',
time: '9:15',
name:['Banjo Barney']
},{
type: 'passenger',
direction: 'east',
time: '9:15',
name:['Flimsy Stick']
}, {
type: 'passenger',
direction: 'west',
time: '9:30',
name:['Big Red']
},{
type: 'passenger',
direction: 'west',
time: '9:35',
name:['Hathaway Anne']
}];
let remaining = new Map();
let pairs = match(items, item => item, remaining);
console.log('pairs',...pairs);
console.log('remaining',...remaining.values());
答案 0 :(得分:1)
封装&空间复杂性:
您对Set
的使用是合适的,但可以通过封装匹配功能并删除全局变量来改进代码。我建议一个生成器,它产生如下匹配对,空间复杂度降低:
// Match items with first equal match:
function* match(items, equals, remaining = new Set()) {
items:
for (let item of items) {
for (let candidate of remaining) {
if (equals(item, candidate)) {
remaining.delete(candidate);
yield [item, candidate];
continue items;
}
}
remaining.add(item);
}
}
// Example:
let items = [1, 2, 5, 3, 3, 4, 2, 1, 4];
let remaining = new Set();
let pairs = match(items, (a, b) => a == b, remaining);
console.log(...pairs);
console.log(...remaining);

根据您的商品,您需要提供匹配的equals
回调。在你的情况下:
let pairs = match(
items,
(a, b) =>
a.type !== b.type &&
a.direction === b.direction &&
a.time === b.time,
remaining
);
<强>优化强>
如果您可以将请求映射到原始标识值,则可以使用简单的地图查找替换for (let i of memo) { ... }
循环。然后,将n个项目配对的时间复杂度降低到O(n)
。
但是,由于您没有匹配相同的&#39;项目但具有相反type
属性的项目,此优化不能直接应用。您需要添加另一个回调,它会为我们提供匹配项的预期ID。
此外,由于您可能会遇到具有相同身份的多个请求,因此您需要multimap:
// Multimap insertion:
function insert(map, key, value) {
let values = map.get(key);
if (values) values.push(value);
else map.set(key, [value]);
}
// Multimap retrieval:
function retrieve(map, key) {
let values = map.get(key);
if (values) {
let value = values.pop();
if (values.length === 0) map.delete(key);
return value;
}
}
// Match items with first identical match:
function* match(items, identity, match, remaining) {
for (let item of items) {
let candidate = retrieve(remaining, match(item));
if (candidate) yield [item, candidate];
else insert(remaining, identity(item), item);
}
}
// Example:
let items = [{
type: 'driver',
direction: 'east',
time: '9:15',
name: ['Archibald Trump']
}, {
type: 'passenger',
direction: 'east',
time: '9:15',
name: ['Bacon Eater']
}, {
type: 'passenger',
direction: 'east',
time: '9:15',
name: ['Banjo Barney']
}, {
type: 'passenger',
direction: 'east',
time: '9:15',
name: ['Flimsy Stick']
}, {
type: 'passenger',
direction: 'west',
time: '9:30',
name: ['Big Red']
}, {
type: 'passenger',
direction: 'west',
time: '9:35',
name: ['Hathaway Anne']
}];
let remaining = new Map();
let pairs = match(
items,
item => '' + (item.type == 'driver') + item.direction + item.time,
item => '' + (item.type == 'passenger') + item.direction + item.time,
remaining
);
console.log(...pairs);
console.log(...remaining.values());
&#13;
上述实现的运行时复杂性不容易确定,因为它取决于Array.shift()
和Array.push()
的运行时复杂性。但是,如果我们假设这种关键冲突很少或假设JavaScript引擎在摊销的常量时间内执行这两种方法,我们仍然可以预期n项的O(n)运行时复杂性。
答案 1 :(得分:0)
地图比数组更快。您每次都可以比循环遍历数组更快地访问映射键。以下是使用地图的示例。
var pairs = [];
var memo = {};
function pair(item) {
var key = item.type.toString() + item.direction + item.time;
if(memo[key]) {
pairs.push(item);
delete memo[key];
} else {
memo[key] = item;
}
}
var ar = [{
type: true,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: true,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: true,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: true,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: true,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: true,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}, {
type: false,
direction: false,
time: '9:00'
}];
for (let it of ar) {
pair(it);
}
console.log('matching pairs: ', pairs);
console.log('left over nonmatching pairs:', Object.values(memo));
&#13;