Reputation: 2134
In JavaScript, I have an array of objects and an input value like this:
const inputVal = 'foo';
const objArray = [
{title: 'blahaa', type: 'foobar'},
{title: 'foobar', type: 'wohoo'},
{title: 'foobar', type: 'foobar'},
{title: 'foobar', type: 'aaaabaa'},
{title: 'foobar', type: 'moo'},
{title: 'aaah', type: 'foogoo'},
{title: 'foohiii', type: 'foobar'},
{title: 'aaah', type: 'foobar'},
{title: 'foodoo', type: 'aaaabaa'},
{title: 'gaaaaaah', type: 'foobar'},
{title: 'foobar', type: 'foogoo'},
];
As you can see, all elements in the array have properties starting with "foo" in either the title or the type. Also, all elements are unique, the same title and/or type can be in several elements, but the same combination of both cannot appear twice.
I want to sort this array in the following way:
inputVal
inputVal
but not type
inputVal
but not title
The example list would be sorted as following:
const objArray = [
{title: 'foobar', type: 'foobar'}, // Criterium 1
{title: 'foohiii', type: 'foobar'}, // Criterium 1
{title: 'foobar', type: 'foogoo'}, // Criterium 1
{title: 'foobar', type: 'aaaabaa'}, // Criterium 2
{title: 'foodoo', type: 'aaaabaa'}, // Criterium 2
{title: 'foobar', type: 'moo'}, // Criterium 2
{title: 'foobar', type: 'wohoo'}, // Criterium 2
{title: 'aaah', type: 'foobar'}, // Criterium 3
{title: 'blahaa', type: 'foobar'}, // Criterium 3
{title: 'gaaaaaah', type: 'foobar'}, // Criterium 3
{title: 'aaah', type: 'foogoo'}, // Criterium 3
];
I tried using array.prototype.sort(callback)
with several different callback functions, but I don't seem to get the correct one. Can anyone help me?
Upvotes: 0
Views: 68
Reputation: 402
Here is another solution, probably less efficient due to the use of multiple regex.
const objArray = [
{title: 'blahaa', type: 'foobar'},
{title: 'foobar', type: 'wohoo'},
{title: 'foobar', type: 'foobar'},
{title: 'foobar', type: 'aaaabaa'},
{title: 'foobar', type: 'moo'},
{title: 'aaah', type: 'foogoo'},
{title: 'foohiii', type: 'foobar'},
{title: 'aaah', type: 'foobar'},
{title: 'foodoo', type: 'aaaabaa'},
{title: 'gaaaaaah', type: 'foobar'},
{title: 'foobar', type: 'foogoo'}
];
const input = "foo";
const sortedObjArray = [
objArray.sort((a, b) => {
const
regex = new RegExp("^(" + input + ")?(.*)", "i"),
titleAExec = regex.exec(a.title),
typeAExec = regex.exec(a.type),
titleBExec = regex.exec(b.title),
typeBExec = regex.exec(b.type)
const
titleComparison = titleAExec[2].localeCompare(titleBExec[2]),
typeComparison = typeAExec[2].localeCompare(typeBExec[2])
if (titleAExec[1] && !titleBExec[1])
return -1
else if (titleBExec[1] && !titleAExec[1])
return 1
if (typeAExec[1] && !typeBExec[1])
return -1
else if (typeBExec[1] && !typeAExec[1])
return 1
if (typeComparison === 0)
return titleComparison
return typeComparison;
})
]
console.log(sortedObjArray)
Upvotes: 0
Reputation: 386883
You could chanin the criteria and sort by the three groups first and then by the values.
const
value = 'foo',
start = (v => s => s.startsWith(v))(value),
array = [{ title: 'blahaa', type: 'foobar' }, { title: 'foobar', type: 'wohoo' }, { title: 'foobar', type: 'foobar' }, { title: 'foobar', type: 'aaaabaa' }, { title: 'foobar', type: 'moo' }, { title: 'aaah', type: 'foogoo' }, { title: 'foohiii', type: 'foobar' }, { title: 'aaah', type: 'foobar' }, { title: 'foodoo', type: 'aaaabaa' }, { title: 'gaaaaaah', type: 'foobar' }, { title: 'foobar', type: 'foogoo' }];
array.sort((a, b) =>
(start(b.title) && start(b.type)) - (start(a.title) && start(a.title))
|| start(b.title) - start(a.title)
|| start(b.type) - start(a.type)
|| a.type.localeCompare(b.type)
|| a.title.localeCompare(b.title)
);
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 3
Reputation: 1
You can try the following:
To improve performance, process all subarrays asynchronously. Divide and Conquer wins!
Upvotes: -1