For this coding challenge, the idea is to rename files based on how many times they appear in an array. The first instance of an item does not need to be renamed.
So we expect
['myFile', 'anotherFile', 'family-picture', 'myFile', 'another-file', 'myFile']
To equal
['myFile', 'anotherFile', 'family-picture', 'myFile(1)', 'anotherFile(1)', 'myFile(2)']
And so far I've created:
function renameFiles (array) {
let map = {};
let final = [];
array.forEach((value) => {
if (!map[value]) {
map[value] = 0;
}
map[value] += 1;
});
let dups = [];
for (let key in map) {
if (map[key] > 1) {
let count = map[key];
while (count > 0) {
dups.push(key);
count--;
}
}
}
if (!dups.length) {
return array;
}
let dupNumber = dups.length - 1;
while (dupNumber >= 0) {
for (let i = array.length; i >= 0; i--) {
if (dups.includes(array[i])) {
final.unshift(array[i] + '(' + dupNumber + ')');
dupNumber --;
} else {
final.unshift(array[i]);
}
}
}
final = final.filter((element) => element !== undefined);
return final.map((element) => element.replace('(0)', ''));
}
console.log(renameFiles(['myFile', 'anotherFile', 'family-picture', 'myFile', 'another-file', 'myFile']));
This is working except that for the last test-spec in the challenge - we need to NOT add numbers after the items in the final list if that number already exists in the original list.
I.e. we expect
['a(1)', 'a(6)', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',];
To equal
['a(1)', 'a(6)', 'a', 'a(2)', 'a(3)', 'a(4)', 'a(5)', 'a(7)', 'a(8)', 'a(9)', 'a(10)', 'a(11)',]
So perhaps there's a better initial approach for this problem than the one I created?
Here's a pastebin of the jasmine test-specs for this challenge.
And also a JSFiddle where I have the test-specs entered, but I don't know how to change HTML or CSS in the other windows to JS.
What if you do a single reduce to count the number of each, then as you iterate through to append the numbers, keep track of an offset starting at 0 which increases both when the same value is found and whenever an attempted name already exists?
Note: it got a little finicky with offsets due to needing it to start at 1, but only if there are 2 or more, but this seems to work:
function renameFiles(array) {
const offsets = {};
const counts = array.reduce((countObj, fn) => {
countObj[fn] = (countObj[fn] || 0) + 1;
offsets[fn] = 0;
return countObj;
}, {});
return array.map(val => {
++offsets[val];
while (offsets[val] > 1 && array.includes(`${val}(${offsets[val] - 1})`)) {
++offsets[val];
}
return offsets[val] === 1 ? val : `${val}(${offsets[val] - 1})`;
});
}