JS recursive mergeSort with objects - javascript

Hihi,
My question is simple. I'm trying to implement mergesort but having a limitation with the structure of my project
I have a file called sort.js
const selSort = require('./selectionSort');
const bubSort = require('./bubbleSort');
const inSort = require('./insertionSort');
const merSort = require('./mergeSort');
const sort = (arr) => {
const array = arr;
return {
...selSort(array),
...bubSort(array),
...inSort(array),
...merSort(array),
};
};
As you can see I'm trying to implement multiple sort algorithm and make an object
well, now while I started doing the MergeAlgorithm (a recursive sort algorithm) I faced with the problem of the objects in JavaScript
const merge = (left, right) => {
const result = [];
while (left.length && right.legnth) {
result.push(left[0] < right[0] ? left.shifth() : right.shifth());
}
return [...result, ...left, ...right];
};
const merSort = (array) => ({
mergeSort: () => {
if (array.length === 1) {
return array;
}
const middle = Math.floor(array.length);
const leftArr = array.slice(0, middle);
const rightArr = array.slice(middle);
return merge(this(leftArr).mergeSort(), this(rightArr).mergeSort());
},
});
module.exports = merSort;
I cant call mergeSort() and pass to it the left and right array without calling itself again.
Is there anyway to solve this?
I tried using this but it didn't worked
I think there is no way to achive what I want

Why are you using the spread operator ( ... ) all the time ? Also why are you reassigning the arr argument to a constant?
This should work just fine
const selSort = require('./selectionSort');
const bubSort = require('./bubbleSort');
const inSort = require('./insertionSort');
const merSort = require('./mergeSort');
const sort = (arr) => {
return {
selSort(arr),
bubSort(arr),
inSort(arr),
merSort(arr),
};
};
Also for the sorting code this should work
function mergeSort(unsortedArray) {
if (unsortedArray.length <= 1) {
return unsortedArray;
}
const middle = Math.floor(unsortedArray.length / 2);
const left = unsortedArray.slice(0, middle);
const right = unsortedArray.slice(middle);
return merge(mergeSort(left,), mergeSort(right));
}
function merge(left, right) {
let resultArray = [],
leftIndex = 0,
rightIndex = 0;
while (leftIndex < left.length && rightIndex < right.length) {
if (left[leftIndex] < right[rightIndex]) {
resultArray.push(left[leftIndex]);
leftIndex++;
} else {
resultArray.push(right[rightIndex]);
rightIndex++;
}
}
return resultArray
.concat(left.slice(leftIndex))
.concat(right.slice(rightIndex));
}
module.exports = mergeSort;

Related

I have a array of string have to find all the common character present from all strings

I have a array of string.
let arr=["robin","rohit","roy"];
Need to find all the common character present in all the strings in array.
Output Eg: r,o
I have tried to create a function for above case with multiple loops but i want to know what should be the efficient way to achive it.
Here's a functional solution which will work with an array of any iterable value (not just strings), and uses object identity comparison for value equality:
function findCommon (iterA, iterB) {
const common = new Set();
const uniqueB = new Set(iterB);
for (const value of iterA) if (uniqueB.has(value)) common.add(value);
return common;
}
function findAllCommon (arrayOfIter) {
if (arrayOfIter.length === 0) return [];
let common = new Set(arrayOfIter[0]);
for (let i = 1; i < arrayOfIter.length; i += 1) {
common = findCommon(common, arrayOfIter[i]);
}
return [...common];
}
const arr = ['robin', 'rohit', 'roy'];
const result = findAllCommon(arr);
console.log(result);
const arr = ["roooooobin","rohit","roy"];
const commonChars = (arr) => {
const charsCount = arr.reduce((sum, word) => {
const wordChars = word.split('').reduce((ws, c) => {
ws[c] = 1;
return ws;
}, {});
Object.keys(wordChars).forEach((c) => {
sum[c] = (sum[c] || 0) + 1;
});
return sum;
}, {});
return Object.keys(charsCount).filter(key => charsCount[key] === arr.length);
}
console.log(commonChars(arr));
Okay, the idea is to count the amount of times each letter occurs but only counting 1 letter per string
let arr=["robin","rohit","roy"];
function commonLetter(array){
var count={} //object used for counting letters total
for(let i=0;i<array.length;i++){
//looping through the array
const cache={} //same letters only counted once here
for(let j=0;j<array[i].length;j++){
//looping through the string
let letter=array[i][j]
if(cache[letter]!==true){
//if letter not yet counted in this string
cache[letter]=true //well now it is counted in this string
count[letter]=(count[letter]||0)+1
//I don't say count[letter]++ because count[letter] may not be defined yet, hence (count[letter]||0)
}
}
}
return Object.keys(count)
.filter(letter=>count[letter]===array.length)
.join(',')
}
//usage
console.log(commonLetter(arr))
No matter which way you choose, you will still need to count all characters, you cannot get around O(n*2) as far as I know.
arr=["robin","rohit","roy"];
let commonChars = sumCommonCharacters(arr);
function sumCommonCharacters(arr) {
data = {};
for(let i = 0; i < arr.length; i++) {
for(let char in arr[i]) {
let key = arr[i][char];
data[key] = (data[key] != null) ? data[key]+1 : 1;
}
}
return data;
}
console.log(commonChars);
Here is a 1 liner if anyone interested
new Set(arr.map(d => [...d]).flat(Infinity).reduce((ac,d) => {(new RegExp(`(?:.*${d}.*){${arr.length}}`)).test(arr) && ac.push(d); return ac},[])) //{r,o}
You can use an object to check for the occurrences of each character. loop on the words in the array, then loop on the chars of each word.
let arr = ["robin","rohit","roy"];
const restWords = arr.slice(1);
const result = arr[0].split('').filter(char =>
restWords.every(word => word.includes(char)))
const uniqueChars = Array.from(new Set(result));
console.log(uniqueChars);

React Native State not updating with an empty Array

Hi stackoverflow people I know this has been asked about a million times. However I don't think I have found an answer to my problem!
Long story short I am updating a state in my react native app only if a statement is true. What I am experiencing is this state not being updated somehow.
const emptyArray = []
const [collapsed, setCollapsed] = useState(true);
const [selectedGem, setSelectedGem] = useState(false);
const [usedGem, setUsedGem] = useState(emptyArray);
const [selectedPropType, setSelectedPropType] = useState('all');
const randomItem = (items) => {
return items[Math.floor(Math.random()*items.length)];
}
const getRandomQuestion = () => {
let selectableGems = gems
const maxGems = selectableGems.length;
let tempGems = [];
if(usedGem.length >= maxGems) {
setUsedGem(emptyArray)
}
for (let i=0; i<maxGems; i++)
{
if(usedGem.length === 0 || usedGem.find(gem => gem === i) === undefined) {
tempGems.push(i)
}
}
const randomGemNumber = randomItem(tempGems)
setUsedGem([...usedGem, randomGemNumber])
setSelectedGem(selectableGems[randomGemNumber])
}
Basically if(usedGem.length >= maxGems) {happens only when all the gems have been randomised once (there are 130 item in the gems variable). I'd expect then the usedGem to be empty in the for but this isn't the case.
I have tried a few solutions I found without luck. I know this has to do with async but I can't figure it out! Anyone could help me please?
Here this might help. The thing is you can't get instant update after setting state
const getRandomQuestion = () => {
let selectableGems = gems
const maxGems = selectableGems.length;
let tempGems = [];
let gems = Array.from(usedGem);
if(gems.length >= maxGems) {
gems = []
}
for (let i=0; i<maxGems; i++)
{
if(gems.length === 0 || gems.find(gem => gem === i) === undefined) {
tempGems.push(i)
}
}
const randomGemNumber = randomItem(tempGems)
setUsedGem([...gems, randomGemNumber])
setSelectedGem(selectableGems[randomGemNumber])
}

My function does not return the expected output and I can't figure out why; can somebody point out something I'm missing? [duplicate]

This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 3 years ago.
my function has to take 2 arrays and if one of the arrays is shorter than the other it needs to fill in the blanks with nulls.
so i could do this easier now that i think about it but i would really like to know what i have missed.
the specific part of my code is the nested forEach loops i cant understand that when i invoke my function like this
fillSquare([1,2,3],[1,2,3,4,5])
I get [[1,2,3,4,5],[1,2,3,4,5]] instead of [[1,2,3,null,null][1,2,3,4,5]]
const fillSquare = arr => {
const maxArrayLength = Math.max(
...arr.map(arr => {
return arr.length;
})
);
let arrayMatrix = new Array(arr.length).fill(
new Array(maxArrayLength).fill(null)
);
arr.forEach((arry, mainIndex) => {
arry.forEach((item, subIndex) => {
console.log(mainIndex, "<--main", "sub-->", subIndex, "=", item);
arrayMatrix[mainIndex][subIndex] = item;
});
});
console.log(arrayMatrix);
return arrayMatrix;
};
When debugging, it seems:
let arrayMatrix = new Array(arr.length).fill(
new Array(maxArrayLength).fill(null)
);
// arrayMatrix[1] == arrayMatrix[0] => true
is only creating 1 array instance. setting 1 value on one sets it on both.
heres how to fix your issue
let arrayMatrix = new Array(arr.length).fill(0).map( _ => new Array(maxArrayLength).fill(null));
this is my version - now immutable
function fillSquare(arr) {
let clone = [...arr]
let maxDepth = arr.reduce( (c, subarr) => c = Math.max(c, subarr.length), 0)
clone.forEach((subarr, index) => {
let len = clone[index].length;
clone[index].length = maxDepth;
clone[index].fill(null, len, maxDepth);
})
return clone;
}
the import notes are you can set the length and fill the gaps. Also check out reduce if you need.
const fillSquare = function(arr){
let minLengthArr = arr[0];
let maxLength = arr[1].length;
if(arr[1].length < arr[0].length){
minLengthArr= arr[1];
maxLength = arr[0].length;
}
let itemsToPush = maxLength - minLengthArr.length;
for(let i=0;i<itemsToPush;i++){
minLengthArr.push(null);
}
return arr;
}
var r = fillSquare([[1,2,3],[1,2,3,4,5]]);
console.log(r);

How to sort an array using values from an enum?

I want to sort elements of an array using an enum, I would like to know how to do it, I have tried with a switch statement with no success.
const enum Order {
Start = 'Start',
Run = 'Run',
End = 'End',
}
const predicate (a, b) => // TODO
const data = [Order.End, Order.Run, Order.Start]
const result = data.sort(predicate)
// wanted result is: // Start, Run, End
Normally with an enum, the value is already comparable.
const enum Order {
Start = 0,
Run = 1,
End = 2,
}
const data = [Order.End, Order.Run, Order.Start];
const result = data.sort();
console.log(result);
A non-constant enum can even be mapped to the string values, as shown here:
enum Order {
Start = 0,
Run = 1,
End = 2,
}
const data = [Order.End, Order.Run, Order.Start];
const result = data.sort();
console.log(result.map((val) => Order[val]));
But in your case, you could convert them into an easily sortable value if necessary (assuming you desire to avoid alphabetical ordering).
const enum Order {
Start = 'Start',
Run = 'Run',
End = 'End',
}
const predicate = (a, b) => {
const map = {};
map[Order.Start] = 1;
map[Order.Run] = 2;
map[Order.End] = 3;
if (map[a] < map[b]) {
return -1;
}
if (map[a] > map[b]) {
return 1;
}
return 0;
}
const data = [Order.End, Order.Run, Order.Start];
const result = data.sort(predicate);
console.log(result);
I created a function in typescript based on previous answer to order objects from an enum.
export function sortByStatus(a: Element, b: Element): number {
const map = new Map<Status, number>();
map.set(Status.DONE, 0);
map.set(Status.ERROR, 1);
map.set(Status.PROCESSING, 2);
map.set(Status.NONE, 3);
if (map.get(a.status) < map.get(b.status)) {
return -1;
}
if (map.get(a.status) > map.get(b.status)) {
return 1;
}
return 0;
}
Furthermore, I include a mini test to check its functionality.
it('check sortByStatus', () => {
expect(sortByStatus(a, b)).toBeLessThanOrEqual(1);
expect(sortByStatus(b, a)).toBeGreaterThanOrEqual(-1);
expect(sortByStatus(a, a)).toBe(0);
});

javascript (es6) return value of filter in forEach

I have function like below.
If the value of the filter is an array with more than 4 I want to return just the key.
For instance const result = gethitedShips(); // result be 1 or 2 but I get undefined
I totally got confused where to return what
getHitShips = () => {
const { players } = this.props;
return Object.keys(players).forEach(key => {
const hitShips = players[key].ships.filter(ship => ship.health <= 0);
if (hitShips.length >= 5) return key;
return null;
});
};
You could filter the keys by checking the length
const getHitedShips = () => {
const { players } = this.props;
return Object
.keys(players)
.filter(key => players[key].ships.filter(ship => ship.health <= 0).length >= 5);
};

Categories