Menggabungkan kumpulan data yang tumpang tindih

Mengingat beberapa kumpulan data yang mungkin/mungkin tidak tumpang tindih pada satu atau lebih kolom, saya ingin menggabungkan kumpulan data tersebut secara dinamis.

Apakah ada pustaka atau cuplikan kode yang akan menggabungkan kumpulan data dengan cara ini? Bagaimana kalau melakukannya menggunakan satu kolom sebagai kunci?

CONTOH: Menggabungkan dua kumpulan data, menggunakan beberapa kolom sebagai kunci (Judul Buku, Penulis)

Masukan, Kumpulan Data 1

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

Masukan, Kumpulan Data 2

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

Keluaran, Set Data Munging

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

Saya telah melakukan beberapa penelitian dan tidak ada hasil yang berguna (kebanyakan tentang penggabungan objek JSON satu kali dalam struktur yang sama (yaitu, menambahkan data, bukan menggabungkan kumpulan data yang berbeda)).

Saya mencari Java/JavaScript, menggunakan data JSON/XML/CSV (sesuai urutan preferensi) tetapi akan menerima bahasa lain dengan asumsi bahwa algoritma tersebut dapat di-porting.

Saya juga akan mempertimbangkan untuk menerima contoh di mana hal ini dilakukan pada satu kolom saja.


person kwah    schedule 26.07.2014    source sumber


Jawaban (1)


Yah, saya tidak akan mencari perpustakaan untuk sesuatu yang begitu sederhana. Sebaliknya cobalah membangun solusi sendiri.

Pertama-tama Anda dapat JSON.parse() string apa pun untuk mengubahnya menjadi objek. Kemudian, Anda bisa meneruskan kedua objek ini ke dalam fungsi yang terlihat seperti ini.

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;
}

Perhatikan bahwa mergeSets() memanggil contains() yang intinya adalah sebagai berikut.

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;
}

Ini sebenarnya tidak terlalu sulit seperti yang Anda lihat. Maaf untuk beberapa nama variabel. Ini ditulis dengan tergesa-gesa. Selain itu, Anda menyebutkan dalam contoh kumpulan hasil bahwa Anda ingin bidang yang tidak tersedia ditampilkan sebagai null yang tidak sesuai karena null biasanya menunjukkan referensi kosong. Sebaliknya, saya mengabaikannya. Mengakses bidang tersebut pada objek dalam array yang tidak memilikinya akan menghasilkan undefined yang sangat masuk akal.

Selain itu, berikut ini adalah batasan kode pada biola. Anda dapat mengeditnya untuk meringankan keterbatasan ini dan membuatnya lebih kuat.

  1. Ini terkait dengan format data yang Anda sebutkan dalam pertanyaan Anda. Untuk membuatnya berfungsi pada himpunan arbitrer, Anda dapat memeriksa keberadaan properti menggunakan Object.hasOwnProperty() dalam perulangan for-in dan menambahkan properti yang diperlukan sehingga menghasilkan penggabungan.

  2. Itu tidak menangani duplikat dalam set.

http://jsfiddle.net/x5Q5g/

Sunting: Oh! Omong-omong, kodenya adalah JavaScript dan format datanya bisa berupa JSON asalkan Anda menggunakan JSON.parse() dan JSON.stringify().

Sunting: Pembaruan berikut meniadakan batasan pertama yang disebutkan di atas. Perhatikan bahwa Anda perlu memasukkan kunci untuk membandingkan berdasarkan, secara eksplisit.

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/

Satu pembaruan terakhir: Berikut adalah cara membuatnya menerima sejumlah kunci. Saya lupa bahwa Anda memerlukan banyak dukungan kunci. Maaf!

Anda perlu mengubah hal berikut ini.

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/

Biola terakhir dan kode diatasnya sudah selesai. Tanpa referensi apa pun! Dan bersifat generik. Akan bekerja dengan sejumlah kunci sebagai argumen.

person Siddharth    schedule 26.07.2014
comment
Ini sepertinya titik awal yang menarik, terima kasih. Bagian yang tidak diselesaikan dengan solusi ini adalah bahwa struktur kumpulan data, dan kolom tempat kumpulan data ini akan digabungkan, bersifat dinamis (yaitu, tidak diketahui hingga waktu proses/disediakan oleh pengguna). Ini mungkin hanya masalah menarik ini ke parameter..? - person kwah; 26.07.2014
comment
Terlambat untuk mengedit komentar saya, tetapi komentar 'perpustakaan' dimaksudkan sebagai petunjuk bahwa saya sedang mencari sesuatu yang umum, bukannya dikodekan ke kumpulan data tertentu. Saya akan melihat pengeditan pertanyaan agar lebih jelas :). - person kwah; 26.07.2014
comment
Izinkan saya mengedit solusi saya dan menjadikannya umum untuk Anda. Tunggu. - person Siddharth; 26.07.2014
comment
Saya telah memberi suara positif kepada Anda, tetapi karena belum lengkap, saya ragu untuk menandai sebagai jawaban yang benar (misalnya, masih memiliki referensi ke .numPages). Saya akan bermain untuk membuatnya lebih umum. Dengan asumsi tidak ada jawaban yang lebih lengkap yang diposting sementara ini, saya dengan senang hati menandai ini sebagai benar setelah saya selesai (dan membagikan biolanya kembali) karena Anda akan sangat membantu :) - person kwah; 26.07.2014
comment
Ups. Saya lupa menghapus baris itu. Ia bekerja tanpanya! Anda tidak memerlukan referensi apa pun ke numPages. Periksa biola terakhir. - person Siddharth; 26.07.2014
comment
Oh keren, bersorak! Diterima saat Anda menjawab pertanyaan yang saya ajukan! :) Anda berhak mendapatkan lebih dari sekadar satu perwakilan suara positif/penerimaan karena bersikap responsif dan membantu! - person kwah; 26.07.2014
comment
Ah. Jangan khawatir tentang hal itu. Kau selalu diterima. Inilah isi situs web ini. - person Siddharth; 26.07.2014