实现带有JSON阵列交叉值
我有一个包含JSON对象数组如实现带有JSON阵列交叉值
validTags = [{"tag":"tag1"}, {"tag":"tag2"}];
和
items = [{"id":123456, "tag":"tag1"}, {"id":123456, "tag":"tag2"}, {"id":7890, "tag":"tag1"}];
,我试图找出的ID的同时具有“标签”从第一个数组开始。
E.g.输出将是:
[{"id":123456, "tag":"tag1 tag2"}]
将两个匹配标签组合成一个字符串。
任何想法我应该如何去做这件事?我正在和Javascript聊天室中的一些SO用户聊天,他们建议可以使用数组交叉口,但我不完全确定如何使用这个来获得JSON的预期结果:(
全部答案/帮助表示赞赏
非常感谢
下面是使用对象和数组的溶液:
validTags = [{"tag":"tag1"}, {"tag":"tag2"}];
items = [{"id":123456, "tag":"tag1"}, {"id":123456, "tag":"tag2"}, {"id":7890, "tag":"tag1"}];
accumulate = {};
// Make use of the hashing of JavaScript objects to merge the tags.
items.forEach(function(e) {
if(accumulate[e.id] == undefined) accumulate[e.id] = [e.tag];
else accumulate[e.id].push(e.tag);
});
// Convert the object into an array. The field 'tags' is still an array.
var result0 = [];
for(var id in accumulate) result0.push({"id": id, tags: accumulate[id]});
var result = result0.filter(
// First we cross out those do not contain every tag.
function(e) { return validTags.every(
function(e1) { return e.tags.indexOf(e1.tag) != -1; }); })
// Then we make the 'tags' array into a string.
.map(function(e) { return {"id": e.id, "tags": e.tags.join(" ")}; });
完美运作。解释基本步骤的评论也很棒!谢谢 – Mac 2013-02-15 16:13:42
这应该这样做:
var validTags = [{"tag":"tag1"}, {"tag":"tag2"}];
var items = [{"id":123456, "tag":"tag1"}, {"id":123456, "tag":"tag2"}, {"id":7890, "tag":"tag1"}];
var actualTags = validTags.map(function(obj){return obj.tag}),
comparableTags = actualTags.sort().join(" ");
var tagsById = items.reduce(function(map, item) {
if (item.id in map)
map[item.id].push(item.tag);
else
map[item.id] = [ item.tag ];
return map;
}, {});
var result = [];
for (var id in tagsById) {
var tags = tagsById[id].sort().join(" ");
if (comparableTags == tags) // Yai, array comparison by content!
result.push({id: id, tag:tags});
}
return result;
如果您正在使用Underscore,你可以使用pluck
代替map
和groupBy
而不是reduce
;总之:
var comparableTags = _.pluck(validTags, "tag").sort().join(" ");
return _.chain(items).groupBy("id").map(function(id, tags) {
return {id:id, tag:tags.sort().join(" ");
}.filter(function(obj) {
return obj.tag == comparableTags;
}).value();
阿好吧brill(我正在使用下划线:D)。有了上面的代码,如果我有var validTags = [{“tag”:“tag1”}];是否有可能返回包含tag1的项目,即使它们也包含tag2?所以目前如果它只是在有效标签中的“tag1”,我会返回ID 7890,但是我也可以返回ID 123456(因为它的tag1已分配给它)? – Mac 2013-02-15 15:37:00
然后不要使用我的字符串比较,但像'if(_difference(actualTags,obj.tags).length == 0)'(其中'obj.tags'仍然是一个数组)。不知道是否有更具表现力和高性能的方式 – Bergi 2013-02-15 15:39:53
感谢您的帮助 – Mac 2013-02-15 16:18:22
有在JavaScript中没有固定的操作,但是他们很容易界定,例如:
intersection = function(a, b) {
return a.filter(function(x) { return b.indexOf(x) >= 0 })
}
针对您的特殊任务,首先转换validTags
到一个列表:
vtags = validTags.map(function(x) { return x.tag })
然后计算一个十字路口,将items
中的每个tag
属性转换为一个数组:
results = items.filter(function(x) {
return intersection(x.tag.split(/\s+/), vtags).length == vtags.length
})
感谢您的解释 – Mac 2013-02-15 16:17:44
的'tag1'和'tag2'变量字符串? – Bergi 2013-02-15 15:20:25
哎呀,是的,已编辑,以反映这一点! – Mac 2013-02-15 15:21:44