Some fixes and refactoring in sorting objects
This commit is contained in:
parent
346517b947
commit
b011b196e1
|
@ -302,26 +302,24 @@ export function removeAll (paths) {
|
||||||
* @return {Array}
|
* @return {Array}
|
||||||
*/
|
*/
|
||||||
export function sort (eson, path, order = null) {
|
export function sort (eson, path, order = null) {
|
||||||
// console.log('sort', path, order)
|
|
||||||
|
|
||||||
const compare = order === 'desc' ? compareDesc : compareAsc
|
const compare = order === 'desc' ? compareDesc : compareAsc
|
||||||
const reverseCompare = (a, b) => -compare(a, b)
|
const reverseCompare = (a, b) => -compare(a, b)
|
||||||
const object = getIn(eson, path)
|
const object = getIn(eson, path)
|
||||||
|
|
||||||
if (object[META].type === 'Array') {
|
if (object[META].type === 'Array') {
|
||||||
const items = object.map(item => item[META].value)
|
const items = object.map(item => item[META].value)
|
||||||
const createAction = (value, fromIndex, toIndex, array) => ({
|
const createAction = ({item, fromIndex, toIndex}) => ({
|
||||||
op: 'move',
|
op: 'move',
|
||||||
from: compileJSONPointer(path.concat(String(fromIndex))),
|
from: compileJSONPointer(path.concat(String(fromIndex))),
|
||||||
path: compileJSONPointer(path.concat(String(toIndex)))
|
path: compileJSONPointer(path.concat(String(toIndex)))
|
||||||
})
|
})
|
||||||
|
|
||||||
const actions = sortWithComparator(items, compare, createAction)
|
const actions = sortWithComparator(items, compare).map(createAction)
|
||||||
|
|
||||||
// when no order is provided, test whether ordering ascending
|
// when no order is provided, test whether ordering ascending
|
||||||
// changed anything. If not, sort descending
|
// changed anything. If not, sort descending
|
||||||
if (!order && isEmpty(actions)) {
|
if (!order && isEmpty(actions)) {
|
||||||
return sortWithComparator(items, reverseCompare, createAction)
|
return sortWithComparator(items, reverseCompare).map(createAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
return actions
|
return actions
|
||||||
|
@ -329,32 +327,45 @@ export function sort (eson, path, order = null) {
|
||||||
else { // object[META].type === 'Object'
|
else { // object[META].type === 'Object'
|
||||||
|
|
||||||
const props = object[META].props
|
const props = object[META].props
|
||||||
const createAction = (value, fromIndex, toIndex, objectProps) => ({
|
const createAction = ({item, beforeItem, fromIndex, toIndex}) => ({
|
||||||
op: 'move',
|
op: 'move',
|
||||||
from: compileJSONPointer(path.concat(value)),
|
from: compileJSONPointer(path.concat(item)),
|
||||||
path: compileJSONPointer(path.concat(value)),
|
path: compileJSONPointer(path.concat(item)),
|
||||||
meta: {
|
meta: {
|
||||||
before: props[toIndex]
|
before: beforeItem
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const actions = sortWithComparator(props, compare, createAction)
|
const actions = sortWithComparator(props, compare).map(createAction)
|
||||||
|
|
||||||
// when no order is provided, test whether ordering ascending
|
// when no order is provided, test whether ordering ascending
|
||||||
// changed anything. If not, sort descending
|
// changed anything. If not, sort descending
|
||||||
if (!order && isEmpty(actions)) {
|
if (!order && isEmpty(actions)) {
|
||||||
return sortWithComparator(props, reverseCompare, createAction)
|
return sortWithComparator(props, reverseCompare).map(createAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: comment
|
/**
|
||||||
function sortWithComparator (items, comparator, createAction) {
|
* Sort an array with items using given comparator, and generate move actions
|
||||||
|
* (json patch) to apply the ordering.
|
||||||
|
*
|
||||||
|
* @param {Array} items
|
||||||
|
* @param {function (a, b)} comparator Accepts to values,
|
||||||
|
* returns 1 when a is larger than b
|
||||||
|
* returns 0 when a is equal to b
|
||||||
|
* returns -1 when a is smaller than b
|
||||||
|
* @return {Array.<{item: *, beforeItem: *, fromIndex: number, toIndex: number}>}
|
||||||
|
* Returns an array with move actions that need to be
|
||||||
|
* performed to order the items of the array.
|
||||||
|
* This can be turned into json-patch actions
|
||||||
|
*/
|
||||||
|
function sortWithComparator (items, comparator) {
|
||||||
const orderedItems = items.slice()
|
const orderedItems = items.slice()
|
||||||
|
|
||||||
let actions = []
|
let moveActions = []
|
||||||
for (let i = 0; i < orderedItems.length; i++) {
|
for (let i = 0; i < orderedItems.length; i++) {
|
||||||
let firstIndex = i
|
let firstIndex = i
|
||||||
for (let j = i; j < orderedItems.length; j++) {
|
for (let j = i; j < orderedItems.length; j++) {
|
||||||
|
@ -364,15 +375,21 @@ function sortWithComparator (items, comparator, createAction) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i !== firstIndex) {
|
if (i !== firstIndex) {
|
||||||
const firstItem = orderedItems[firstIndex]
|
const item = orderedItems[firstIndex]
|
||||||
|
const beforeItem = orderedItems[i]
|
||||||
orderedItems.splice(firstIndex, 1)
|
orderedItems.splice(firstIndex, 1)
|
||||||
orderedItems.unshift(firstItem)
|
orderedItems.unshift(item)
|
||||||
|
|
||||||
actions.push(createAction(firstItem, firstIndex, i))
|
moveActions.push({
|
||||||
|
item,
|
||||||
|
fromIndex: firstIndex,
|
||||||
|
toIndex: i,
|
||||||
|
beforeItem
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return actions
|
return moveActions
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -75,3 +75,10 @@ test('sort nested Object', t => {
|
||||||
t.deepEqual(patchEson(eson, sort(eson, ['obj'], 'asc')).data.obj[META].props, ['a', 'b', 'c'])
|
t.deepEqual(patchEson(eson, sort(eson, ['obj'], 'asc')).data.obj[META].props, ['a', 'b', 'c'])
|
||||||
t.deepEqual(patchEson(eson, sort(eson, ['obj'], 'desc')).data.obj[META].props, ['c', 'b', 'a'])
|
t.deepEqual(patchEson(eson, sort(eson, ['obj'], 'desc')).data.obj[META].props, ['c', 'b', 'a'])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('sort nested Object (larger)', t => {
|
||||||
|
const eson = jsonToEson({obj: {h:1, c:1, e:1, d:1, g:1, b:1, a:1, f:1}})
|
||||||
|
const actual = patchEson(eson, sort(eson, ['obj'])).data
|
||||||
|
|
||||||
|
t.deepEqual(actual.obj[META].props, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
|
||||||
|
})
|
||||||
|
|
Loading…
Reference in New Issue