如何消除hadoop mapreduce中的重复文件名?

发布于 2025-01-03 08:21:02 字数 135 浏览 0 评论 0原文

我想消除 hadoop mapreduce 倒排索引程序输出中的重复文件名。例如,输出类似于 - things : doc1,doc1,doc1,doc2 但我希望它像 事物:doc1,doc2

I want to eliminate duplicate filenames in my output of the hadoop mapreduce inverted index program. For example, the output is like - things : doc1,doc1,doc1,doc2 but I want it to be like
things : doc1,doc2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧竹 2025-01-10 08:21:02

那么您想要删除映射的重复项,即您想要将中间值列表减少为没有重复项的输出列表。我最好的选择是简单地将 reduce() 方法中的 Iterator 转换为 java Set 并对其进行迭代更改:

while (values.hasNext()) {
    if (!first)
    toReturn.append(", ") ;
    first = false;
    toReturn.append(values.next().toString());
}

不幸的是,

Set<Text> valueSet = new HashSet<Text>();
while (values.hasNext()) {
    valueSet.add(values.next());
}

for(Text value : valueSet) {
    if(!first) {
        toReturn.append(", ");
    }
    first = false;
    toReturn.append(value.toString());
}

我不知道有什么更好(更简洁)的方法将迭代器转换为集合。

这应该比橙色的解决方案具有更小的时间复杂度,但内存消耗更高。

@编辑:短一点:

Set<Text> valueSet = new HashSet<Text>();
while (values.hasNext()) {
    Text next = values.next();
    if(!valueSet.contains(next)) {
        if(!first) {
            toReturn.append(", ");
        }
        first = false;
        toReturn.append(value.toString());
        valueSet.add(next);
    }
}

包含应该是(就像添加一样)恒定时间,所以现在应该是 O(n) 。

Well you want to remove duplicates which were mapped, i.e. you want to reduce the intermediate value list to an output list with no duplicates. My best bet would be to simply convert the Iterator<Text> in the reduce() method to a java Set and iterate over it changing:

while (values.hasNext()) {
    if (!first)
    toReturn.append(", ") ;
    first = false;
    toReturn.append(values.next().toString());
}

To something like:

Set<Text> valueSet = new HashSet<Text>();
while (values.hasNext()) {
    valueSet.add(values.next());
}

for(Text value : valueSet) {
    if(!first) {
        toReturn.append(", ");
    }
    first = false;
    toReturn.append(value.toString());
}

Unfortunately I do not know of any better (more concise) way of converting an Iterator to a Set.

This should have a smaller time complexity than orange's solution but a higher memory consumption.

@Edit: a bit shorter:

Set<Text> valueSet = new HashSet<Text>();
while (values.hasNext()) {
    Text next = values.next();
    if(!valueSet.contains(next)) {
        if(!first) {
            toReturn.append(", ");
        }
        first = false;
        toReturn.append(value.toString());
        valueSet.add(next);
    }
}

Contains should be (just like add) constant time so it should be O(n) now.

如歌彻婉言 2025-01-10 08:21:02

要以最少的代码更改来做到这一点,只需添加一个 if 语句来检查您要附加的内容是否已在 toReturn:

if (!first)
    toReturn.append(", ") ;
first = false;
toReturn.append(values.next().toString());

gets 更改为

String v = values.next().toString()
if (toReturn.indexOf(v) == -1) {  // indexOf returns -1 if it is not there
    if (!first) {
        toReturn.append(", ") ;
    }
    toReturn.append(v);
    first = false
}

上面的解决方案有点慢是因为它每次都必须遍历整个字符串来查看该字符串是否存在。可能最好的方法是使用 HashSet 来收集项目,然后将 HashSet 中的值组合成最终输出字符串。

To do this with the minimal amount of code change, just add an if-statement that checks to see if the thing you are about to append is already in toReturn:

if (!first)
    toReturn.append(", ") ;
first = false;
toReturn.append(values.next().toString());

gets changed to

String v = values.next().toString()
if (toReturn.indexOf(v) == -1) {  // indexOf returns -1 if it is not there
    if (!first) {
        toReturn.append(", ") ;
    }
    toReturn.append(v);
    first = false
}

The above solution is a bit slow because it has to traverse the entire string every time to see if that string is there. Likely the best way to do this is to use a HashSet to collect the items, then combining the values in the HashSet into a final output string.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文