合并重叠数据集

时间:2014-07-26 07:59:50

标签: javascript java json merge dataset

鉴于可能/可能不会在一列或多列上重叠的多个数据集,我希望动态合并数据集。

是否有以这种方式合并数据集的库或代码段?如何使用单个列作为键来执行此操作?

示例:合并两个数据集,使用多个列作为键(BookTitle,作者)

输入,数据集1

BookTitle, Author, Publisher
title1, author1, publisher1
title2, author2, publisher2
title3, author3, publisher3

输入,数据集2

BookTitle, Author, NumPages
title4, author4, numPages4
title7, author7, numPages7
title5, author5, numPages5
title3, author33, numPages3
title2, author2, numPages2

输出,Munged数据集

BookTitle, Author, Publisher, NumPages
title1, author1, publisher1, _null_
title2, author2, publisher2, numPages2
title3, author3, publisher3, _null_
title4, author4, _null_, numPages4
title5, author5, _null_, numPages5
title7, author7, _null_, numPages7
title3, author33, _null_, numPages3

我做了一些研究,没有立即有用(主要是关于JSON对象在同一结构中的一次合并(即附加数据,而不是合并不同的数据集))。

我正在寻找一个Java / JavaScript,使用JSON / XML / CSV数据(按照优先顺序)但是会接受其他语言,假设这些算法可以移植。

我还会考虑接受仅在单个列上进行此操作的示例。

1 个答案:

答案 0 :(得分:1)

好吧,我不会真的想找到一个如此简单的库。而是尝试自己构建解决方案。

您可以先JSON.parse()将任何字符串转换为对象。然后,您可以将这两个对象传递给看起来像这样的函数。

function mergeSets(first, second) {
    var result = first;
    second.forEach(function (item, index, array) {
        var resultIndex = contains(result, item);
        if (resultIndex === -1) {
            result.push(item);
        } else {
            result[resultIndex].numPages = item.numPages;
        }
    });
    return result;
}

请注意mergeSets()调用contains(),基本上如下所示。

function contains(set, object) {
    var solution = -1;
    set.forEach(function (item, index, array) {
        if (item.bookTitle == object.bookTitle && item.author == object.author) {
            solution = index;
        }
    });
    return solution;
}

你可以看到真的不是太难。对不起,有些变量名称。这是匆忙写的。另外,您在结果集的示例中提到,您希望不可用的字段显示为null这是不合适的,因为null通常表示空引用。相反,我忽略了它们。访问数组中没有它们的对象上的那些字段将导致undefined完全正确。

此外,以下是小提琴中代码的限制。您可以对其进行编辑以减轻这些限制并使其更加健壮。

  1. 它与您在问题中提到的数据格式相关联。为了使其适用于任意集,您可以在for-in循环中使用Object.hasOwnProperty()检查属性是否存在,并添加必要的属性以导致合并。

  2. 无论如何它都不会处理集合内的重复。

  3. http://jsfiddle.net/x5Q5g/

    编辑:哦!顺便说一句,代码是JavaScript,如果您使用JSON.parse()JSON.stringify(),数据格式可以是JSON。

    编辑:以下更新否定了上述第一个限制。请注意,您需要明确地传递密钥以进行比较。

    function contains(set, object, key) {
        var solution = -1;
        set.forEach(function (item, index, array) {
            if (item[key] === object[key]) {
                solution = index;
            }
        });
        return solution;
    }
    
    function mergeSets(first, second, key) {
        var result = first;
        second.forEach(function (item, index, array) {
            var resultIndex = contains(result, item, key);
            if (resultIndex === -1) {
                result.push(item);
            } else {
                result[resultIndex].numPages = item.numPages;
                for (var property in item) {
                    if (item.hasOwnProperty(property)) {
                        if (!result[resultIndex].hasOwnProperty(property)) {
                            result[resultIndex].property = item.property;
                        }
                    }
                }
            }
        });
        return result;
    }
    
    var solution = mergeSets(firstSet, secondSet, "bookTitle");
    console.log(solution);
    

    http://jsfiddle.net/s6HqL/

    最后一次更新:以下是如何让它接受任意数量的密钥。我忘记了你需要多个关键支持。遗憾!

    您需要更改以下内容。

    function contains(set, object, keys) {
        var solution = -1;
        set.forEach(function (item, index, array) {
            var selfItem = item;
            var allKeys = keys.every(function (item, index, array) {
                if (selfItem[item] === object[item]) {
                    return true;
                }
            });
            if (allKeys) {
                solution = index;
            }
        });
        return solution;
    }
    
    function mergeSets(first, second) {
        var result = first;
        var keys = Array.prototype.slice.call(arguments, 2);
        second.forEach(function (item, index, array) {
            var resultIndex = contains(result, item, keys);
            if (resultIndex === -1) {
                result.push(item);
            } else {
                for (var property in item) {
                    if (item.hasOwnProperty(property)) {
                        if (!result[resultIndex].hasOwnProperty(property)) {
                            var hello = result[resultIndex];
                            hello[property] = item[property];
                        }
                    }
                }
            }
        });
        return result;
    }
    
    var solution = mergeSets(firstSet, secondSet, "bookTitle", "author");
    console.log(solution);
    

    http://jsfiddle.net/s6HqL/3/

    上面的最后一个小提琴和代码已经完成。没有任何参考!并且是通用的。可以使用任意数量的键作为参数。