I have the following function:
const sort = (query) => (choiceA, choiceB) => choiceA.name.toLowerCase().localeCompare(choiceB.name.toLowerCase()),
It is used as follow:
newSearches = newSearches.sort(sort(query));
For example, in this example, tarascon
should be first result, etc...
const query = 't';
const choices = [
{
"name": "Marseille 1er arrondissement"
},
{
"name": "Marseille 2ème arrondissement"
},
{
"name": "Marseille 3ème arrondissement"
},
{
"name": "Marseille 4ème arrondissement"
},
{
"name": "Marseille 5ème arrondissement"
},
{
"name": "Marseille 6ème arrondissement"
},
{
"name": "Marseille 7ème arrondissement"
},
{
"name": "Marseille 8ème arrondissement"
},
{
"name": "Marseille 9ème arrondissement"
},
{
"name": "Marseille 10ème arrondissement"
},
{
"name": "Marseille 11ème arrondissement"
},
{
"name": "Marseille 12ème arrondissement"
},
{
"name": "Marseille 13ème arrondissement"
},
{
"name": "Marseille 14ème arrondissement"
},
{
"name": "Marseille 15ème arrondissement"
},
{
"name": "Marseille 16ème arrondissement"
},
{
"name": "Le Tholonet"
},
{
"name": "Saint-Marc-Jaumegarde"
},
{
"name": "Beaurecueil"
},
{
"name": "Saint-Antonin-sur-Bayon"
},
{
"name": "Aix-en-Provence"
},
{
"name": "Saint-Étienne-du-Grès"
},
{
"name": "Mas-Blanc-des-Alpilles"
},
{
"name": "Mimet"
},
{
"name": "Simiane-Collongue"
},
{
"name": "Port-de-Bouc"
},
{
"name": "Coudoux"
},
{
"name": "La Destrousse"
},
{
"name": "Lamanon"
},
{
"name": "Puyloubier"
},
{
"name": "Saint-Paul-lès-Durance"
},
{
"name": "Vernègues"
},
{
"name": "Saint-Savournin"
},
{
"name": "Gardanne"
},
{
"name": "Aurons"
},
{
"name": "Ventabren"
},
{
"name": "Peypin"
},
{
"name": "Vauvenargues"
},
{
"name": "Vitrolles"
},
{
"name": "Berre-l'Étang"
},
{
"name": "Miramas"
},
{
"name": "Tarascon"
},
{
"name": "Les Pennes-Mirabeau"
},
{
"name": "Gignac-la-Nerthe"
},
{
"name": "Allauch"
},
{
"name": "Arles"
},
{
"name": "Saint-Rémy-de-Provence"
},
{
"name": "Châteauneuf-les-Martigues"
},
{
"name": "Port-Saint-Louis-du-Rhône"
},
{
"name": "Septèmes-les-Vallons"
},
{
"name": "Cornillon-Confoux"
},
{
"name": "Saint-Chamas"
},
{
"name": "Cassis"
},
{
"name": "Fos-sur-Mer"
},
{
"name": "Salon-de-Provence"
},
{
"name": "Saint-Martin-de-Crau"
},
{
"name": "Bouc-Bel-Air"
},
{
"name": "La Barben"
},
{
"name": "Pélissanne"
},
{
"name": "Rognac"
},
{
"name": "Charleval"
},
{
"name": "Roquevaire"
},
{
"name": "Mallemort"
},
{
"name": "Plan-de-Cuques"
},
{
"name": "Auriol"
},
{
"name": "Aubagne"
},
{
"name": "Lambesc"
},
{
"name": "Gémenos"
},
{
"name": "Eyguières"
},
{
"name": "Grans"
},
{
"name": "Saintes-Maries-de-la-Mer"
},
{
"name": "Carnoux-en-Provence"
},
{
"name": "Cabriès"
},
{
"name": "Jouques"
},
{
"name": "Martigues"
},
{
"name": "Éguilles"
},
{
"name": "Paradou"
},
{
"name": "Maussane-les-Alpilles"
},
{
"name": "Les Baux-de-Provence"
},
{
"name": "Trets"
},
{
"name": "Sénas"
},
{
"name": "La Fare-les-Oliviers"
},
{
"name": "Meyreuil"
},
{
"name": "La Ciotat"
},
{
"name": "Ceyreste"
},
{
"name": "Saint-Estève-Janson"
},
{
"name": "Le Puy-Sainte-Réparade"
},
{
"name": "Carry-le-Rouet"
},
{
"name": "La Roque-d'Anthéron"
},
{
"name": "Meyrargues"
},
{
"name": "Lançon-Provence"
},
{
"name": "Marignane"
},
{
"name": "Fuveau"
},
{
"name": "La Bouilladisse"
},
{
"name": "Belcodène"
},
{
"name": "Saint-Victoret"
},
{
"name": "Le Rove"
},
{
"name": "Saint-Cannat"
},
{
"name": "Venelles"
},
{
"name": "Cuges-les-Pins"
},
{
"name": "Riboux"
},
{
"name": "Peynier"
},
{
"name": "Châteauneuf-le-Rouge"
},
{
"name": "Rousset"
},
{
"name": "Istres"
},
{
"name": "Ensuès-la-Redonne"
},
{
"name": "La Penne-sur-Huveaune"
},
{
"name": "Roquefort-la-Bédoule"
},
{
"name": "Rognes"
},
{
"name": "Gréasque"
},
{
"name": "Peyrolles-en-Provence"
},
{
"name": "Velaux"
},
{
"name": "Mouriès"
},
{
"name": "Saint-Mitre-les-Remparts"
},
{
"name": "Aureille"
},
{
"name": "Cadolive"
},
{
"name": "Sausset-les-Pins"
},
{
"name": "Alleins"
},
{
"name": "Fontvieille"
},
{
"name": "Fourques"
},
{
"name": "Artigues"
},
{
"name": "Rians"
},
{
"name": "Plan-d'Aups-Sainte-Baume"
},
{
"name": "Saint-Zacharie"
},
{
"name": "Nans-les-Pins"
},
{
"name": "Pourrières"
},
{
"name": "Pertuis"
},
{
"name": "Mirabeau"
},
{
"name": "La Bastidonne"
},
{
"name": "Beaumont-de-Pertuis"
},
{
"name": "Puyvert"
},
{
"name": "Cucuron"
},
{
"name": "Lourmarin"
},
{
"name": "Cadenet"
},
{
"name": "Vaugines"
},
{
"name": "Vitrolles-en-Lubéron"
},
{
"name": "Grambois"
},
{
"name": "Cabrières-d'Aigues"
},
{
"name": "Peypin-d'Aigues"
},
{
"name": "Sannes"
},
{
"name": "Ansouis"
},
{
"name": "La Bastide-des-Jourdans"
},
{
"name": "La Tour-d'Aigues"
},
{
"name": "La Motte-d'Aigues"
},
{
"name": "Lauris"
},
{
"name": "Villelaure"
},
{
"name": "Saint-Martin-de-la-Brasque"
}
];
const sort = (query) => (choiceA, choiceB) => !isNaN(query) || (
choiceA.name.toLowerCase().localeCompare(choiceB.name.toLowerCase()) && query.indexOf(choiceA.name.toLowerCase()) === -1
);
const filter = (query) => (choice) => choice.name.toLowerCase().includes(query.toLowerCase());
document.getElementById('search').addEventListener('click', () => {
const q = document.getElementById('query').value;
const newSearches = choices.filter(filter(q)).sort(sort(q));
document.getElementById('result').innerHTML = JSON.stringify(newSearches.map(s => s.name), null, 2);
}, true);
#result {
display: block;
width: 100vw;
}
<input id="query" type="text" />
<button id="search" type="button">search<button>
<pre id="result"></pre>
enter code here
So far, this will sort alphabetically just by comparing the names, regardless of the query, how can I update it in order to sort it alphabetically depending on the query providing?
You could change it to something like this:
const sort = (query) => (choiceA, choiceB) => {
const name1 = choiceA.name.toLowerCase(),
name2 = choiceB.name.toLowerCase(),
q = query.toLowerCase();
return (name2.startsWith(q) - name1.startsWith(q))
|| (name1.localeCompare(name2))
};
First take the difference between
name2.startsWith(q) - name1.startsWith(q)
startsWith
returns a boolean and they coerced to 0 or 1 when they are used in a mathematical context
true - false === 1
false - true === -1
true - true === 0
If name1
starts with the query
but name2
doesn't, then it becomes false - true
which is -1
. So, choiceA
is prioritized compared to choiceB
If both start with query
or both don't start with query
, then the the subtraction returns 0
. This is a falsy value. So, in this case, the ||
operator will check the second condition which will sort it alphabetically.
Here's a snippet:
const choices=[{name:"Marseille 1er arrondissement"},{name:"Marseille 2ème arrondissement"},{name:"Marseille 3ème arrondissement"},{name:"Marseille 4ème arrondissement"},{name:"Marseille 5ème arrondissement"},{name:"Marseille 6ème arrondissement"},{name:"Marseille 7ème arrondissement"},{name:"Marseille 8ème arrondissement"},{name:"Marseille 9ème arrondissement"},{name:"Marseille 10ème arrondissement"},{name:"Marseille 11ème arrondissement"},{name:"Marseille 12ème arrondissement"},{name:"Marseille 13ème arrondissement"},{name:"Marseille 14ème arrondissement"},{name:"Marseille 15ème arrondissement"},{name:"Marseille 16ème arrondissement"},{name:"Le Tholonet"},{name:"Saint-Marc-Jaumegarde"},{name:"Beaurecueil"},{name:"Saint-Antonin-sur-Bayon"},{name:"Aix-en-Provence"},{name:"Saint-Étienne-du-Grès"},{name:"Mas-Blanc-des-Alpilles"},{name:"Mimet"},{name:"Simiane-Collongue"},{name:"Port-de-Bouc"},{name:"Coudoux"},{name:"La Destrousse"},{name:"Lamanon"},{name:"Puyloubier"},{name:"Saint-Paul-lès-Durance"},{name:"Vernègues"},{name:"Saint-Savournin"},{name:"Gardanne"},{name:"Aurons"},{name:"Ventabren"},{name:"Peypin"},{name:"Vauvenargues"},{name:"Vitrolles"},{name:"Berre-l'Étang"},{name:"Miramas"},{name:"Tarascon"},{name:"Les Pennes-Mirabeau"},{name:"Gignac-la-Nerthe"},{name:"Allauch"},{name:"Arles"},{name:"Saint-Rémy-de-Provence"},{name:"Châteauneuf-les-Martigues"},{name:"Port-Saint-Louis-du-Rhône"},{name:"Septèmes-les-Vallons"},{name:"Cornillon-Confoux"},{name:"Saint-Chamas"},{name:"Cassis"},{name:"Fos-sur-Mer"},{name:"Salon-de-Provence"},{name:"Saint-Martin-de-Crau"},{name:"Bouc-Bel-Air"},{name:"La Barben"},{name:"Pélissanne"},{name:"Rognac"},{name:"Charleval"},{name:"Roquevaire"},{name:"Mallemort"},{name:"Plan-de-Cuques"},{name:"Auriol"},{name:"Aubagne"},{name:"Lambesc"},{name:"Gémenos"},{name:"Eyguières"},{name:"Grans"},{name:"Saintes-Maries-de-la-Mer"},{name:"Carnoux-en-Provence"},{name:"Cabriès"},{name:"Jouques"},{name:"Martigues"},{name:"Éguilles"},{name:"Paradou"},{name:"Maussane-les-Alpilles"},{name:"Les Baux-de-Provence"},{name:"Trets"},{name:"Sénas"},{name:"La Fare-les-Oliviers"},{name:"Meyreuil"},{name:"La Ciotat"},{name:"Ceyreste"},{name:"Saint-Estève-Janson"},{name:"Le Puy-Sainte-Réparade"},{name:"Carry-le-Rouet"},{name:"La Roque-d'Anthéron"},{name:"Meyrargues"},{name:"Lançon-Provence"},{name:"Marignane"},{name:"Fuveau"},{name:"La Bouilladisse"},{name:"Belcodène"},{name:"Saint-Victoret"},{name:"Le Rove"},{name:"Saint-Cannat"},{name:"Venelles"},{name:"Cuges-les-Pins"},{name:"Riboux"},{name:"Peynier"},{name:"Châteauneuf-le-Rouge"},{name:"Rousset"},{name:"Istres"},{name:"Ensuès-la-Redonne"},{name:"La Penne-sur-Huveaune"},{name:"Roquefort-la-Bédoule"},{name:"Rognes"},{name:"Gréasque"},{name:"Peyrolles-en-Provence"},{name:"Velaux"},{name:"Mouriès"},{name:"Saint-Mitre-les-Remparts"},{name:"Aureille"},{name:"Cadolive"},{name:"Sausset-les-Pins"},{name:"Alleins"},{name:"Fontvieille"},{name:"Fourques"},{name:"Artigues"},{name:"Rians"},{name:"Plan-d'Aups-Sainte-Baume"},{name:"Saint-Zacharie"},{name:"Nans-les-Pins"},{name:"Pourrières"},{name:"Pertuis"},{name:"Mirabeau"},{name:"La Bastidonne"},{name:"Beaumont-de-Pertuis"},{name:"Puyvert"},{name:"Cucuron"},{name:"Lourmarin"},{name:"Cadenet"},{name:"Vaugines"},{name:"Vitrolles-en-Lubéron"},{name:"Grambois"},{name:"Cabrières-d'Aigues"},{name:"Peypin-d'Aigues"},{name:"Sannes"},{name:"Ansouis"},{name:"La Bastide-des-Jourdans"},{name:"La Tour-d'Aigues"},{name:"La Motte-d'Aigues"},{name:"Lauris"},{name:"Villelaure"},{name:"Saint-Martin-de-la-Brasque"}];
const sort = (query) => (choiceA, choiceB) => {
const name1 = choiceA.name.toLowerCase(),
name2 = choiceB.name.toLowerCase(),
q = query.toLowerCase();
return (name2.startsWith(q) - name1.startsWith(q))
|| (name1.localeCompare(name2))
};
const filter = (query) => (choice) => choice.name.toLowerCase().includes(query.toLowerCase());
document.getElementById('search').addEventListener('click', () => {
const q = document.getElementById('query').value;
const newSearches = choices.filter(filter(q)).sort(sort(q));
document.getElementById('result').innerHTML = JSON.stringify(newSearches.map(s => s.name), null, 2);
}, true);
#result {
display: block;
width: 100vw;
}
<input id="query" type="text" />
<button id="search" type="button">search<button>
<pre id="result"></pre>