Saya memiliki dua objek: oldObj
dan newObj
.
Data di oldObj
digunakan untuk mengisi formulir dan newObj
merupakan hasil dari pengguna mengubah data dalam formulir ini dan mengirimkannya.
Kedua objek dalam, yaitu. mereka memiliki properti yang merupakan objek atau array objek dll - mereka dapat n level dalam, sehingga algoritma diff harus bersifat rekursif.
Sekarang saya tidak hanya perlu mencari tahu apa yang diubah (seperti pada tambah / perbarui / dihapus) dari oldObj
ke newObj
, tetapi juga bagaimana cara terbaik untuk mewakilinya.
Sejauh ini pikiranku adalah untuk hanya membangun genericDeepDiffBetweenObjects
metode yang akan mengembalikan objek pada formulir {add:{...},upd:{...},del:{...}}
tetapi kemudian aku berpikir: orang lain pasti membutuhkan ini sebelumnya.
Jadi ... apakah ada yang tahu perpustakaan atau sepotong kode yang akan melakukan ini dan mungkin memiliki cara yang lebih baik untuk mewakili perbedaan (dengan cara yang masih berseri JSON)?
Memperbarui:
Saya telah memikirkan cara yang lebih baik untuk mewakili data yang diperbarui, dengan menggunakan struktur objek yang sama dengan newObj
, tetapi mengubah semua nilai properti menjadi objek pada formulir:
{type: '<update|create|delete>', data: <propertyValue>}
Jadi jika newObj.prop1 = 'new value'
dan oldObj.prop1 = 'old value'
itu akan diaturreturnObj.prop1 = {type: 'update', data: 'new value'}
Pembaruan 2:
Itu menjadi benar-benar berbulu ketika kita sampai ke properti yang array, karena array [1,2,3]
harus dihitung sama dengan [2,3,1]
, yang cukup sederhana untuk array tipe nilai berbasis seperti string, int & bool, tetapi menjadi sangat sulit untuk ditangani ketika datang ke array tipe referensi seperti objek dan array.
Contoh array yang harus ditemukan sama:
[1,[{c: 1},2,3],{a:'hey'}] and [{a:'hey'},1,[3,{c: 1},2]]
Tidak hanya cukup rumit untuk memeriksa jenis kesetaraan nilai yang dalam ini, tetapi juga untuk mencari cara yang baik untuk mewakili perubahan yang mungkin terjadi.
sumber
newObj
dihasilkan oleh nilai membaca kode js dari formulir di DOM. Ada beberapa cara untuk menjaga keadaan dan melakukan ini lebih mudah, tetapi saya ingin menjadikannya tanpa kewarganegaraan sebagai latihan. Saya juga mencari seni sebelumnya untuk melihat bagaimana orang lain mungkin menangani ini, jika memang ada yang punya.Jawaban:
Saya menulis sebuah kelas kecil yang melakukan apa yang Anda inginkan, Anda dapat mengujinya di sini .
Satu-satunya hal yang berbeda dari proposal Anda adalah bahwa saya tidak menganggapnya
[1,[{c: 1},2,3],{a:'hey'}] and [{a:'hey'},1,[3,{c: 1},2]]
sama, karena saya pikir array tidak sama jika urutan elemen-elemennya tidak sama. Tentu ini bisa diubah jika diperlukan. Kode ini juga dapat ditingkatkan untuk mengambil fungsi sebagai argumen yang akan digunakan untuk memformat objek diff dengan cara yang sewenang-wenang berdasarkan nilai primitif yang diteruskan (sekarang pekerjaan ini dilakukan dengan metode "compareValues").sumber
c
dibuat sebagaiundefined
tetapi harus menjadi string'i am created'
), dan selain itu tidak melakukan apa yang saya butuhkan karena tidak memiliki nilai array mendalam dibandingkan yang merupakan bagian yang paling penting (dan kompleks / sulit). Sebagai catatan, konstruksinya'array' != typeof(obj)
tidak berguna karena array adalah objek yang merupakan instance dari array.{type: ..., data:..}
objek. Apa yang hilang adalah mencari nilai dari array pertama di kedua, tetapi seperti yang saya sebutkan dalam jawaban saya, saya tidak berpikir bahwa array sama jika urutan nilainya tidak sama ([1, 2, 3] is not equal to [3, 2, 1]
menurut saya).[{key: 'value1'}] and [{key: 'value2'}, {key: 'value3'}]
. Sekarang adalah objek pertama dalam array pertama diperbarui dengan "value1" atau "value2". Dan ini adalah contoh sederhana, ini bisa menjadi jauh lebih rumit dengan sarang yang dalam. Jika Anda ingin / perlu perbandingan mendalam bersarang terlepas dari posisi kunci tidak membuat array dari objek, membuat objek dengan objek bersarang seperti misalnya sebelumnya:{inner: {key: 'value1'}} and {inner: {key: 'value2'}, otherInner: {key: 'value3'}}
.Menggunakan Garis Bawah, perbedaan sederhana:
Hasil di bagian
o1
yang sesuai tetapi dengan nilai yang berbeda dio2
:Ini akan berbeda untuk perbedaan dalam:
Seperti yang ditunjukkan oleh @Juhana di komentar, di atas hanya beda a -> b dan tidak reversibel (artinya properti tambahan di b akan diabaikan). Gunakan a -> b -> a:
Lihat http://jsfiddle.net/drzaus/9g5qoxwj/ untuk contoh lengkap + tes + mixins
sumber
omit
akan menjadi perbedaan besar, tetapi salah, jadi termasuk juga untuk perbandingan.r[k] = ... : v
dalamr[k] = ... : {'a':v, 'b':b[k] }
, cara ini Anda bisa melihat dua nilai.{a:1, b:2}
dan{a:1, b:2, c:3}
._.omitBy
bukan_.omit
.Saya ingin menawarkan solusi ES6 ... Ini adalah perbedaan satu arah, artinya akan mengembalikan kunci / nilai dari
o2
yang tidak identik dengan rekan-rekan mereka dio1
:sumber
if(o1[key] === o1[key])
saluran itu BungUncaught SyntaxError: Unexpected token ...
Menggunakan Lodash:
Saya tidak menggunakan kunci / objek / sumber tetapi saya meninggalkannya di sana jika Anda perlu mengaksesnya. Perbandingan objek hanya mencegah konsol mencetak perbedaan ke konsol dari elemen terluar ke elemen terdalam.
Anda dapat menambahkan beberapa logika di dalam untuk menangani array. Mungkin mengurutkan array terlebih dahulu. Ini adalah solusi yang sangat fleksibel.
EDIT
Berubah dari _.merge ke _.mergeDengan pembaruan lodash. Terima kasih Aviron karena memperhatikan perubahan.
sumber
Berikut ini adalah pustaka JavaScript yang dapat Anda gunakan untuk menemukan perbedaan antara dua objek JavaScript:
URL Github: https://github.com/cosmicanant/recursive-diff
Npmjs url: https://www.npmjs.com/package/recursive-diff
Anda dapat menggunakan pustaka rekursif-diff di browser dan juga Node.js. Untuk browser, lakukan hal berikut:
Sedangkan di node.js Anda dapat memerlukan modul 'recursive-diff' dan menggunakannya seperti di bawah ini:
sumber
Saat ini, ada beberapa modul yang tersedia untuk ini. Baru-baru ini saya menulis modul untuk melakukan ini, karena saya tidak puas dengan berbagai modul berbeda yang saya temukan. Namanya
odiff
: https://github.com/Tixit/odiff . Saya juga mendaftar banyak modul yang paling populer dan mengapa mereka tidak dapat diterima di readme ofodiff
, yang dapat Anda lihat jikaodiff
tidak memiliki properti yang Anda inginkan. Ini sebuah contoh:sumber
Ada modul npm dengan lebih dari 500k unduhan mingguan: https://www.npmjs.com/package/deep-object-diff
Saya suka objek seperti representasi perbedaan - terutama mudah untuk melihat strukturnya, ketika sudah diformulasikan.
sumber
Saya telah menggunakan kode ini untuk melakukan tugas yang Anda jelaskan:
ini akan memberi Anda objek baru yang akan menggabungkan semua perubahan antara objek lama dan objek baru dari formulir Anda
sumber
$.extend(true,obj1,obj2)
menggunakan jQuery. Ini sama sekali bukan yang saya butuhkan. Saya perlu perbedaan antara dua objek bukan kombinasi keduanya.Saya telah mengembangkan Fungsi bernama "compareValue ()" dalam Javascript. mengembalikan apakah nilainya sama atau tidak. Saya telah memanggil compareValue () di untuk loop dari satu Objek. Anda bisa mendapatkan perbedaan dua objek dalam diffParams.
sumber
Saya tahu saya terlambat ke pesta, tetapi saya membutuhkan sesuatu yang serupa sehingga jawaban di atas tidak membantu.
Saya menggunakan fungsi $ watch Angular untuk mendeteksi perubahan dalam suatu variabel. Saya tidak hanya perlu tahu apakah properti telah berubah pada variabel, tetapi saya juga ingin memastikan bahwa properti yang berubah bukan bidang sementara yang dihitung. Dengan kata lain, saya ingin mengabaikan sifat-sifat tertentu.
Berikut kodenya: https://jsfiddle.net/rv01x6jo/
Berikut cara menggunakannya:
Semoga ini bisa membantu seseorang.
sumber
Saya hanya menggunakan ramda, untuk menyelesaikan masalah yang sama, saya perlu tahu apa yang diubah pada objek baru. Jadi di sini desain saya.
hasilnya adalah, nama properti dan statusnya.
sumber
Ini adalah versi naskah dari kode @sbgoran
sumber
Ini adalah versi modifikasi dari sesuatu yang ditemukan di gisthub .
sumber
Saya memodifikasi jawaban @ sbgoran sehingga objek diff yang dihasilkan hanya mencakup nilai yang diubah , dan menghilangkan nilai yang sama. Selain itu, ini menunjukkan nilai asli dan nilai yang diperbarui .
sumber
Saya sudah menulis fungsi untuk salah satu proyek saya yang akan membandingkan objek sebagai opsi pengguna dengan klon internal. Itu juga dapat memvalidasi dan bahkan mengganti dengan nilai default jika pengguna memasukkan tipe data yang buruk atau dihapus, dalam javascript murni.
Dalam IE8 100% berfungsi. Diuji berhasil.
/ * hasil
sumber
Fungsi lebih luas dan disederhanakan dari jawaban sbgoran.
Ini memungkinkan pemindaian mendalam dan menemukan kesamaan array.
sumber
Saya tersandung di sini mencoba mencari cara untuk mendapatkan perbedaan antara dua objek. Ini solusi saya menggunakan Lodash:
sumber
Saya mengambil jawaban di atas oleh @sbgoran dan memodifikasinya untuk kasus saya sama dengan pertanyaan yang diperlukan, untuk memperlakukan array sebagai set (mis. Pesanan tidak penting untuk diff)
sumber
Berikut ini solusinya yaitu:
object
tipe)undefined
Pertama-tama kita mendefinisikan antarmuka hasil perbandingan:
dengan kasus perubahan khusus di mana kami ingin tahu apa yang lama dan nilai-nilai baru:
Kemudian kita dapat menyediakan
diff
fungsi yang hanya dua loop (dengan recursivity ifdeep
istrue
):Sebagai contoh, menelepon:
akan kembali:
dan memanggil yang sama dengan
deep
parameter ketiga akan kembali:sumber
Perpustakaan ini adalah salah satu yang tercepat untuk membuat objek terdalam:
https://www.npmjs.com/package/@netilon/differify
sumber