Compare two arrays and extract value that does not match - javascript

I have two arrays here, I would like to compare both array and extract out the values that does not match. The '3' stands for module credit and 'nfu3ai' stands for module code so both of them comes together, which basically means 'nfu3ai' has credit of '3' and 'sjfru1' has credit of '6'. So the problem with my code now is when I compare the two arrays I only get ['nfu3ai'] and not 3 since 'sgvnfs' has a credit of '3' as well so it gets remove.
['6', 'sjfru1', '3', 'nfu3ai', '3', 'sgvnfs']
['3', 'sgvnfs', '6', 'sjfru1']
This is my code:
const set1 = new Set(moduleAndCreditByUser);
const set2 = new Set(moduleToUpdate);
const newModule = [
...moduleAndCreditByUser.filter(item =>
!set2.has(item)),
...moduleToUpdate.filter(item =>
!set1.has(item))];
Results:
['nfu3ai']
I want to get:
['3', 'nfu3ai']

to get the result ['3', 'nfu3ai'], you need to modify the code to take into account the relationship between module credits and module codes. Here's one way to do it
const moduleAndCreditByUser = ['6', 'sjfru1', '3', 'nfu3ai', '3', 'sgvnfs'];
const moduleToUpdate = ['3', 'ST1501', '6', 'ST0007'];
const newModule = [];
for (let i = 0; i < moduleAndCreditByUser.length; i += 2) {
const credit = moduleAndCreditByUser[i];
const code = moduleAndCreditByUser[i + 1];
if (!moduleToUpdate.includes(credit) || !moduleToUpdate.includes(code)) {
newModule.push(credit, code);
}
}
console.log(newModule);
I hope that it could help.

I can't get it, you have an array with six and four values in it. Where is the declared that " '3' stands for module credit and 'nfu3ai' stands for module code"
The array shows only six values ['6', 'sjfru1', '3', 'nfu3ai', '3', 'sgvnfs'], but none of them are together. Maybe you should write it in a multiple Array like
[['6', 'sjfru1'], [ '3', 'nfu3ai'], ['3', 'sgvnfs']]
Is that what you want?
To compare your array you could create a function
function compareArrays(array1, array2) {
if (array1.length !== array2.length) {
return 'Arrays are of different lengths';
}
for (let i = 0; i < array1.length; i++) {
if (array1[i] !== array2[i]) {
return `Values are different at index ${i}. (${array1[i]} vs ${array2[i]})`;
}
}
return 'Arrays have the same values';
}
const array1 = [1, 2, 3, 4];
const array2 = [1, 2, 3, 4];
console.log(compareArrays(array1, array2)); // "Arrays have the same values"
const array3 = [1, 2, 3, 4];
const array4 = [4, 3, 2, 1];
console.log(compareArrays(array3, array4)); // "Values are different at index 0 (1 vs 4)"

Related

JS: sorting based on multiple arrays

I have following three arrays, which defines the order of some texts
arr1 = ['ab', 'bc', 'ca', 'ac']
arr2 = ['lm', 'mn', 'ml']
arr3 = ['ij', 'kj', 'pr']
I want to sort array below based on the array above. Each string of myArray is consists of 5 characters where each 2 character are from the characters of the above 3 arrays. That is, arr1 has the highest priority, arr2 has priority over arr3 but less priority than arr1. arr3 has the lowest priority.
First 2 character of each string in myArray always match at least one string in arr1, middle two character match arr2 and last two character match arr3.
myArray = ['acmnkj', 'bcmlij', 'camnij', 'bcmnij',]
How can I sort myArray so that the results are sorted by arr1, arr2 and arr3. Expected sorted array ['bcmnij', 'bcmlij', 'camnij', 'acmnkj']
How can do this?
const arr1 = ['ab', 'bc', 'ca', 'ac']
const arr2 = ['lm', 'mn', 'ml']
const arr3 = ['ij', 'kj', 'pr']
const myArr = ['acmnkj', 'bcmlij', 'camnij', 'bcmnij']
const f = (s,a,i)=>a.indexOf(s.substring(2*i,2*i+2))
myArr.sort((x,y)=>[arr1,arr2,arr3].reduce((a,c,i)=>a || f(x,c,i)-f(y,c,i),0))
console.log(myArr)
You could take an object with the order of the parts and compare sliced parts against.
const
arr1 = ['ab', 'bc', 'ca', 'ac'],
arr2 = ['lm', 'mn', 'ml'],
arr3 = ['ij', 'kj', 'pr'],
data = ['acmnkj', 'bcmlij', 'camnij', 'bcmnij'],
order = Object.fromEntries([...arr1, ...arr2, ...arr3].map((v, i) => [v, i + 1]));
data.sort((a, b) => {
let i = 0;
while (i < 6) {
const r = order[a.slice(i, i + 2)] - order[b.slice(i, i + 2)];
if (r) return r;
i += 2;
}
return 0;
});
console.log(data);
A slightly different approach with replacing the strings by an order value for comparing by string.
const
getOrder = s => s.replace(/../g, k => order[k]),
arr1 = ['ab', 'bc', 'ca', 'ac'],
arr2 = ['lm', 'mn', 'ml'],
arr3 = ['ij', 'kj', 'pr'],
data = ['acmnkj', 'bcmlij', 'camnij', 'bcmnij'],
order = Object.fromEntries([...arr1, ...arr2, ...arr3].map((v, i) => [v, (i + 1).toString().padStart(2)]));
data.sort((a, b) => getOrder(a).localeCompare(getOrder(b)));
console.log(order)
console.log(data);
You could create an object which maps the priority for each array
createOrder = (arr) => Object.fromEntries(arr.map((c,i) => [c,i]))
and then create an array of orders.
orders = [arr1,arr2,arr3].map(createOrder)
I'm assuming that there could be duplicate strings within the arrays. So, a flat order object is not created.
// orders array
[
{
"ab": 0,
"bc": 1,
"ca": 2,
"ac": 3
},
{
"lm": 0,
"mn": 1,
"ml": 2
},
{
"ij": 0,
"kj": 1,
"pr": 2
}
]
Then sort your array. Get the parts for each string
const partsA = a.match(/.{2}/g)
This can be changed based on your actual data. Here, it matches every 2 characters. If your input is 'ac-mn-kj', you'd be splitting at -.
Then loop until you find a difference in the order of each parts using some.
This works for any number of input arrays or format of the string in myArray
const arr1 = ['ab', 'bc', 'ca', 'ac'],
arr2 = ['lm', 'mn', 'ml'],
arr3 = ['ij', 'kj', 'pr'],
createOrder = (arr) => Object.fromEntries(arr.map((c,i) => [c,i])),
orders = [arr1,arr2,arr3].map(createOrder),
myArray = ['acmnkj', 'bcmlij', 'camnij', 'bcmnij']
myArray.sort((a,b) => {
const partsA = a.match(/.{2}/g) // can change based on your requirement
const partsB = b.match(/.{2}/g)
let returnValue;
partsA.some((p, i) => returnValue = orders[i][p] - orders[i][partsB[i]])
return returnValue
})
console.log(myArray)

I don't under stand why compare Numbers function switch parameters?

I have this function here that compares number to sort an array during the sort it should take a and b parameters problems in console log the parameter go b to a instead as they are stated why is this switching happening ? in other words how the compareNumbers function decide on what is a and what is b.
also is this a native pre defined function by the way ? because taking a and b doesn't make any sense to me.
let array1 = ['6', '10', '9']
let array2 = ['90', '9', '1']
function mergeSortedArrays(arr1, arr2) {
let merge = arr1.concat(arr2)
// merge = ['6', '10', '9','90', '9', '1']
merge.sort(compareNumbers)
function compareNumbers(a, b) {
console.log(a, b);
// a = 10 b = 6
// a = 9 b = 10
return a - b;
}
return merge
}
console.log(mergeSortedArrays(array1, array2));

Getting a stack of 5 elements from an array based on a single index

I'm trying to figure out how to extract 5 array elements from an array based on a single index. The index is gonna be of the element in the middle of those 5 array elements. For example, if I have this array:
let array = ['1', '2', '3', '4', '5', '6', '7']
and an index of 2, I would like to get this array returned to me:
['1', '2', '3', '4', '5']
if the index is 0, I would like to get this array returned to me:
['6', '7', '1', '2', '3']
if the index is 5, I would like to get this array returned to me:
['4', '5', '6', '7', '1']
I hope I'm being able to convey what I'm trying to do. I want the element that corresponds to the index to be in the middle of the array and have the 2 previous and 2 next elements appended as well.
As you can see, when the index is at the end of the array and there are no more elements to append after the index, I begin appending the elements from the start. Vice-versa, when the index is at the start of the array, I prepend elements from the ending of the array. This is the part I can't figure out.
You can add index handling. If index is less that 0 = add length of array to index, if index is more than array length - substract array length from it. It will solve your problem
let array = ['1', '2', '3', '4', '5', '6', '7']
function getArr(arr, idx) {
let newArr = []
for(let i= idx -2; i <= idx +2; i++) {
let currentindex = i
if(i < 0) {
currentindex = i + arr.length
} else if( i >= arr.length) {
currentindex = i - array.length
}
newArr.push(arr[currentindex])
}
return newArr
}
console.log(getArr(array, 0))
console.log(getArr(array, 2))
console.log(getArr(array, 5))
This is a declarative (functional programming) approach:
If the array is a and given index is i we can imagine desired array is:
[i-2, i-1, i, i+1, 1+2]
// Unfortunately Javascript doesn't support [start..end] syntax
But if we try to use that as indices to our array (a) some indices may be out of list unless we can access the list items in a circular way. For example in [1, 2, 3] the 5th item would be 2 (5 mod 3). Such a function should be already written so by a little search:
const arrayItem = (a, i) => a[(i % a.length + a.length) % a.length]
Now here are the steps to convert input array to output as a function named f which takes input array (a) and index (i):
const f = (a, i) => [i - 2, i - 1, i, i + 1, i + 2].map(x => arrayItem(a, x))
or writing it in without dependency:
const array = ['1', '2', '3', '4', '5', '6', '7']
const f = (a, i) => [i - 2, i - 1, i, i + 1, i + 2]
.map(x => a[(x % a.length + a.length) % a.length])
console.log(f(array, 2))
console.log(f(array, 0))
console.log(f(array, 5))
One solution would be to wrap your array with duplicates. Then you can add the length of the array to the index and create your array. This nicely handles edge cases.
function getArr(arr, idx) {
let ary = [...arr, ...arr, ...arr]
let ptr = idx+arr.length;
return ary.slice(ptr-2, ptr+3);
}
let array = ['1', '2', '3', '4', '5', '6', '7']
console.log(getArr(array, 0))
console.log(getArr(array, 2))
console.log(getArr(array, 5))

Compare key values only once in 2 arrays

How can I compare values in arrays:
['1', '2', '3', '4']
['2', '1', '4', '1']
just like:
if (1 > 2) return counter++,
first with first, second with second, third with third. If i do for loops i will do it many more times:
for (let i = 0; i < arr1.length; i++) {
for (let j = 0; j < arr2.length; j++) {
if (Number(arr1[i]) > Number(arr2[j])) {
counter++;
}
}
}
i just want to compare them only once, each key value with each key value. So in this example, counter should be 2
You can use Array.reduce to compare the element of the first array with the second one.
Use 0 as a initial value of the accumulator/counter.
Check if the element of the first array passed in as the second
argument of the reduce callback is greater than the corresponding
element of the second array.
If the the above is true increment the accumulator.
const arr1 = ['1', '2', '3', '4'];
const arr2 = ['2', '1', '4', '1'];
const count = arr1.reduce((accumulator, element, idx) => {
return +arr2[idx] > +element? accumulator + 1 : accumulator;
}, 0);
console.log(count);
Just use 1 for loop like below. Since the arrays have the same length, you can just use the index from the first loop for both.
var arr1 = ['1', '2', '3', '4'];
var arr2 = ['2', '1', '4', '1'];
for (var i = 0; i < arr1.length; i++) {
if (arr1[i] > arr2[i]) {
console.log(arr1[i]);
}
}
You need a single loop and compare the values at the same index.
var array1 = ['1', '2', '3', '4'],
array2 = ['2', '1', '4', '1'],
i,
counter = 0;
for (i = 0; i < array1.length; i++) {
if (+array1[i] > +array2[i]) {
counter++;
}
}
console.log(counter);
You don't need a nested loop for that. You can do that using only single loop.However a cleaner way is using Array.prototype.filter() and getting its length.
let arr1 = ['1', '2', '3', '4']
let arr2 = ['2', '1', '4', '1']
let count = arr1.filter((a,i) => +a > +arr2[i]).length;
console.log(count)

Why is the max value not being returned?

var array1 =[ '100', '5', '2', '30', '4'];
var i=0;
var high=0;
while(i<array1.length)
{
if(high <= array1[i])
{
high = array1[i];
}
i++;
}
console.log(high);
You are using an array of Strings, so when you are doing
high <= array1[i]
You are actually comparing Strings and not Numbers
Change the declaration to something like this:
var array1 = [100, 5, 2, 30, 4];

Categories

Resources