Skip to content
This repository was archived by the owner on Mar 12, 2025. It is now read-only.
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
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,26 @@ Immutable.from([1, 2, 3]);
Immutable([1, 2, 3])
```

## Immutable.sortBy

JavaScript's Array `sort()` is a mutating function and its use will throw an ImmutableError. This has been done rather than override the `sort()` method with one that returns an immutable Array. The rationale for this is that returning an immutable array from the `sort()` function would be a surprising change to the expected behavior for developers unfamiliar with immutables. However, a convenient method for creating a sorted immutable array from an unsorted one is still desirable. This function closes this gap.

```javascript
var array = Immutable([1, 3, 2]);
var sortedArray = Immutable.sortBy(array);
// returns Immutable([1, 2, 3]);
```

This function also accepts an optional sorting function as per the original `sort()`:

```javascript
var array = Immutable([1, 3, 2]);
var sortedArray = Immutable.sortBy(array, function(a, b) {
return b - a;
});
// returns Immutable([3, 2, 1]);
```

## Immutable Array

Like a regular Array, but immutable! You can construct these by passing
Expand Down
37 changes: 37 additions & 0 deletions src/seamless-immutable.js
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,42 @@ function immutableInit(config) {
return result;
}

function sortBy(array, sorter) {
var result = [], i, length, rearranged;

if (!(array instanceof Array)) {
throw new TypeError("The first argument to Immutable#sortBy must be an array.");
}

for (i = 0, length = array.length; i < length; i++) {
result.push(array[i]);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use asMutable() instead of making a mutable copy manually?

result.sort(sorter);

// Test if elements of the array have been rearranged
rearranged = false;
for (i = 0, length = array.length; i < length; i++) {
if(result[i] !== array[i]) {
// Check if both are NaN. Type checks catch cases where isNaN returns true for strings.
if(!(typeof result[i] === "number" && isNaN(result[i]) && typeof array[i] === "number" && isNaN(array[i]))) {
rearranged = true;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should break here

}
}

// If the elements haven't been rearranged, return the original immutable
if(rearranged) {
return makeImmutableArray(result);
} else {
// Ensure that the returned array is immutable
if(isImmutable(array)) {
return array;
} else {
return makeImmutableArray(array);
}
}
}

// Creates plain object to be used for cloning
function instantiatePlainObject() {
return {};
Expand Down Expand Up @@ -719,6 +755,7 @@ function immutableInit(config) {
Immutable.getIn = toStatic(getIn);
Immutable.flatMap = toStatic(flatMap);
Immutable.asObject = toStatic(asObject);
Immutable.sortBy = sortBy;
if (!globalConfig.use_static) {
Immutable.static = immutableInit({
use_static: true
Expand Down
2 changes: 2 additions & 0 deletions test/ImmutableArray.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var testAsMutable = require("./ImmutableArray/test-asMutable.js");
var testSet = require("./ImmutableArray/test-set.js");
var testUpdate = require("./ImmutableArray/test-update.js");
var testGetIn = require("./ImmutableArray/test-getIn.js");
var testSortBy = require("./ImmutableArray/test-sortBy");
var devBuild = require("../seamless-immutable.development.js");
var prodBuild = require("../seamless-immutable.production.min.js");
var getTestUtils = require("./TestUtils.js");
Expand All @@ -25,6 +26,7 @@ var getTestUtils = require("./TestUtils.js");
testSet(config);
testUpdate(config);
testGetIn(config);
testSortBy(config);
});
});
});
58 changes: 58 additions & 0 deletions test/ImmutableArray/test-sortBy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
var JSC = require("jscheck");
var getTestUtils = require("../TestUtils.js");
var assert = require("chai").assert;

module.exports = function(config) {
var Immutable = config.implementation;
var TestUtils = getTestUtils(Immutable);
var check = TestUtils.check;

function dummySorter(a, b) {
if(b > a) {
return 1;
} else if(b < a) {
return -1;
} else {
return 0;
}
}

describe("#sortBy", function() {
it("produces a sorted immutable array", function() {
check(100, [JSC.array(JSC.integer(4), JSC.any())], function(array) {
var immutable = Immutable(array);
var mutable = array.slice();

var resultImmutable = Immutable.sortBy(immutable);
var resultMutable = mutable.slice();
resultMutable.sort();

TestUtils.assertJsonEqual(resultImmutable, resultMutable);
});
});

it("produces a sorted immutable array when provided with a sorter function", function() {
check(100, [JSC.array(JSC.integer(4), JSC.any())], function(array) {
var immutable = Immutable(array);
var mutable = array.slice();

var resultImmutable = Immutable.sortBy(immutable, dummySorter);
var resultMutable = mutable.slice();
resultMutable.sort(dummySorter);

TestUtils.assertJsonEqual(resultImmutable, resultMutable);
});
});

it("returns the same array if it is already sorted", function() {
check(100, [JSC.array(JSC.integer(4), JSC.any())], function(array) {
var mutable = array.slice().sort();
var immutable = Immutable(mutable);

var resultImmutable = Immutable.sortBy(immutable);

assert.strictEqual(resultImmutable, immutable);
});
});
});
};