Skip to content

Array order #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,54 @@ const difference = diffler(before, after);
console.log(difference); // { location: { from: "London", to: "Melbourne" } }
```

## Options

> Experimental

```shell
npm i diffler@next
```

### `respectArrayOrder` defaults to `true`

If you don't care about the order of an array you can disable like so:

```js
const diffler = require("diffler");

const before = { name: "omgaz", locations: ["London", "Melbourne"] };
const after = { name: "omgaz", locations: ["Melbourne", "London"] };

const difference = diffler(before, after, { respectArrayOrder: false });
console.log(difference); // {}
```

However, be aware that additions and removals change the overall shape of the array and so will be seen as an entire array change AFTER the addition and removal.

```js
const diffler = require("diffler");

const before = { name: "omgaz", locations: ["London", "Hong Kong", "Melbourne"] };
const after = { name: "omgaz", locations: ["London", "Melbourne", "Hong Kong" ] };

const difference = diffler(before, after, { respectArrayOrder: false });
console.log(difference); // { locations: { 1: { from: "Hong Kong", to: "Melbourne" }, 2: { from: "Melbourne", to: "Hong Kong" }
```

My advice is to use associative arrays if you do not care about order.

```js
const diffler = require("diffler");

const before = { name: "omgaz", locations: { Melbourne: "Melbourne", London: "London" } };
const after = { name: "omgaz", locations: { London: "London", Melbourne: "Melbourne" } };

const difference = diffler(before, after, { respectArrayOrder: false });
console.log(difference); // { }
```

Maybe in the future, diffler will do this internally and be able to return array new array indexes for these values, it is still my current belief that arrays are ordered and should preserve order.

## Tests

[![Build Status](https://travis-ci.org/omgaz/diffler.svg?branch=master)](https://travis-ci.org/omgaz/diffler)
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 39 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,41 @@
* Author: Gary Chisholm @omgaz
*/

function isArray(toCheck) {
return typeof toCheck === "object" && Boolean(toCheck.length);
}

function isPrimitive(toCheck) {
return toCheck !== Object(toCheck);
}

function validate(val) {
if (isPrimitive(val)) return val;
throw new Error("Cannot ignore array ordering on non-primitive values");
}

var defaultOptions = {
respectArrayOrder: true,
};

/**
* Read in two objects. Iterate over them and return the differences.
*
* @param {object} obj1 First object to compare from.
* @param {object} obj2 Second object to compare against obj1.
* @param {object} options Configure custom behaviour of diffler.
* @param {boolean} options.respectArrayOrder Whether to care if arrays are ordered defaults to true.
* @returns {object} Nested json object of changed properties containing a from and to key.
*/
function diffler(obj1, obj2) {
function diffler(obj1, obj2, options) {
if (typeof options === "undefined") {
options = defaultOptions;
}
var diff = {};

// Iterate over obj1 looking for removals and differences in existing values
for (var key in obj1) {
if (obj1.hasOwnProperty(key) && typeof obj1[key] !== 'function') {
if (obj1.hasOwnProperty(key) && typeof obj1[key] !== "function") {
var obj1Val = obj1[key],
obj2Val = obj2[key];

Expand All @@ -28,8 +50,20 @@ function diffler(obj1, obj2) {
}

// If property is an object then we need to recursively go down the rabbit hole
else if (typeof obj1Val === 'object') {
var tempDiff = diffler(obj1Val, obj2Val);
else if (typeof obj1Val === "object") {
var obj1ValForDiff = obj1Val;
var obj2ValForDiff = obj2Val;
if (isArray(obj1Val) && isArray(obj2Val)) {
// TODO: This is messy, but I've found a bug with arrays of mixed types
// I need to clean this up later.
obj1Val.map(validate);
obj2Val.map(validate);
if (!options.respectArrayOrder) {
obj1ValForDiff = obj1Val.sort();
obj2ValForDiff = obj2Val.sort();
}
}
var tempDiff = diffler(obj1ValForDiff, obj2ValForDiff, options);
if (Object.keys(tempDiff).length > 0) {
if (tempDiff) {
diff[key] = tempDiff;
Expand All @@ -49,7 +83,7 @@ function diffler(obj1, obj2) {

// Iterate over obj2 looking for any new additions
for (key in obj2) {
if (obj2.hasOwnProperty(key) && typeof obj2[key] !== 'function') {
if (obj2.hasOwnProperty(key) && typeof obj2[key] !== "function") {
var obj1Val = obj1[key],
obj2Val = obj2[key];

Expand Down
Loading