\$\begingroup\$
\$\endgroup\$
4
I wanted to implement a selection sort and wanted to make sure that I'm doing it correctly. I wanted to do it in a way that's efficient and use recursion. Please let me know if I am doing this correctly or if there is a better way for me to do it.
/**
* selectionSort
* @param toSort
* @param sorted
* @returns {Array}
*/
function selectionSort(toSort, sorted=[]) {
if (!toSort.length) {
return sorted;
}
let minIndex = findMinimum(toSort);
sorted.push(...toSort.splice(minIndex, 1))
return selectionSort(toSort, sorted);
}
function findMinimum(arr) {
let minIndex=0;
arr.forEach(function (item, index) {
if(item < arr[minIndex]) {
minIndex = index;
}
})
return minIndex;
}
const testCase = [64, 25, 12, 22, 11]
const answer = selectionSort(testCase);
asked Sep 29, 2019 at 18:23
2 Answers 2
\$\begingroup\$
\$\endgroup\$
3
I'd suggest the following changes:
- Use a loop instead of recursion
- Use
for/of
instead of.forEach()
- push a single value instead of using an array with one element in it
- cache the lowest value so far so you don't have to constantly refetch it on every comparison
- Use a temporary array for the sort so the function is non-destructive to the source array (consistent with most array methods)
- Use
const
where you can.
Code:
/**
* selectionSort
* @param toSort (not modified)
* @param sorted (new sorted array)
* @returns {Array}
*/
function selectionSort(toSort, sorted = []) {
if (!toSort.length) {
return sorted;
}
// make copy so we don't modify source
const sortData = toSort.slice();
while (sortData.length) {
const minIndex = findMinimum(sortData);
sorted.push(sortData[minIndex]);
// remove min item from data left to be sorted
sortData.splice(minIndex, 1);
}
return sorted;
}
function findMinimum(arr) {
let minIndex = 0, minValue = arr[0];
for (const [index, item] of arr.entries()) {
if (item < minValue) {
minIndex = index;
minValue = item;
}
}
return minIndex;
}
const testCase = [64, 25, 12, 22, 11]
const answer = selectionSort(testCase);
console.log(answer);
answered Sep 29, 2019 at 19:55
-
\$\begingroup\$ I disagree with
for...of...entries
though. There is nothing wrong with using normalfor
when the use case is exactly what it was designed for. JS communitie's overuse of new constructs where they bring no benefit over the old ones is harmful for code readability and consistency. \$\endgroup\$Tomáš Zato– Tomáš Zato2019年09月30日 11:36:16 +00:00Commented Sep 30, 2019 at 11:36 -
\$\begingroup\$ @TomášZato - I have no problem with a regular
for
loop. The OP was using.forEach()
which I did not think was as good as some type of afor
loop. In this case, the OP actually needs both the index and the value whichfor/of
and.entries()
hands you on a silver platter, thus why I used it. \$\endgroup\$jfriend00– jfriend002019年09月30日 15:23:20 +00:00Commented Sep 30, 2019 at 15:23 -
\$\begingroup\$ I apologize, I read the post again and noticed that I misread
arr.entries
forObject.entries(arr)
.arr.entries
is great. \$\endgroup\$Tomáš Zato– Tomáš Zato2019年09月30日 15:27:13 +00:00Commented Sep 30, 2019 at 15:27
\$\begingroup\$
\$\endgroup\$
2
Review
findMinimum
means to me that you find the minimum value in an array of items. Since your function returns the index instead, call itindexOfMinimum
.- Prefer the use of
const
overlet
if you only assign a variable once:let minIndex = findMinimum(toSort);
->const minIndex = findMinimum(toSort);
. - Use arrow notation to write more compact functions:
function (item, index)
->(item, index) =>
. - Your documentation seems like wasted space. If you document a public function (which is a good thing), put in some effort to write a clear description of the function, not just the name of the method copied.
- Use whitespace to write more idiomatic javascript:
let minIndex=0;
->let minIndex = 0;
if(item < arr[minIndex])
->if (item < arr[minIndex])
Rewritten:
function selectionSort(toSort, sorted=[]) {
if (!toSort.length) {
return sorted;
}
const minIndex = indexOfMinimum(toSort);
sorted.push(...toSort.splice(minIndex, 1))
return selectionSort(toSort, sorted);
}
function indexOfMinimum(arr) {
let minIndex = 0;
arr.forEach((item, index) => {
if (item < arr[minIndex]) {
minIndex = index;
}
})
return minIndex;
}
answered Sep 29, 2019 at 18:46
-
\$\begingroup\$ Those are good suggestions. Thank you. What do you mean by more idiomatic javascript? \$\endgroup\$Christopher Chen– Christopher Chen2019年09月29日 23:51:32 +00:00Commented Sep 29, 2019 at 23:51
-
1\$\begingroup\$ I mean by following more standard practices, or in this case conventions and style guides. \$\endgroup\$dfhwze– dfhwze2019年09月30日 04:17:21 +00:00Commented Sep 30, 2019 at 4:17
Explore related questions
See similar questions with these tags.
default
for
loop is generally more efficient than.forEach()
as there's no function call and new scope involved. Probably best to usefor/of
. \$\endgroup\$for/of
also \$\endgroup\$