Array sort and value change at the same time - javascript

I have an array below and the first number in each array means order.
What I want to do is, whenever I change the order, it resorts the array and re-index it into 2, 3, 4, 5.
const payments = [
[2, paymentName1, '5%'],
[3, paymentName2, '5%'],
[4, paymentName3, '5%'],
[5, paymentName4, '5%']
];
For example, if I change the first array order from 2 to 6, array becomes the one below.
const payments = [
[2, paymentName2, '5%'],
[3, paymentName3, '5%'],
[4, paymentName4, '5%'],
[5, paymentName1, '5%'],
];
what I currently did was to sort it and take for loop to re-order it. and I want to do it in one loop if possible. Please help me with writing this algorithm.
Thanks in advance!
Edit:
payments.sort((a, b) => a[0] - b[0]);
for (const index in payments) {
payments[index][0] = parseInt(index) + 2;
}
This is my current function. Would there be a better way to do?
thanks!

After you sort, just loop over the array and assign the new order values incrementally. There is no "better" here.
const payments = [
[2, "paymentName1", '5%'],
[3, "paymentName2", '5%'],
[4, "paymentName3", '5%'],
[5, "paymentName4", '5%']
];
function setOrder(index, newOrder) {
payments[index][0] = newOrder;
payments.sort(([a], [b]) => a - b);
for (let i = 0; i < payments.length; i++) payments[i][0] = i + 2;
}
setOrder(0, 6);
console.log(payments);
The time complexity is determined by the call to sort: O(nlogn).
Alternatively, you could use binary search to find the target index where the mutated element should go, and then rotate the array elements accordingly. Then the time complexity will be O(n). Although this has a better time complexity, the overhead of JavaScript code will make that for arrays of moderate sizes you'll get faster results with sort.

Related

How to get these 2D array elements summed if there are duplicates?

I have seen a couple of examples, but handling arrays with 2 elements in it and I was wondering what changes would have to be made so that this one gets summed by comparing the first element and calculating the 4th elements
array =
[
[2, 'name1','something',15],
[3, 'name10','something',5],
[5, 'name20','something',20],
[2, 'name15','something',3]
]
Expected Result
array =
[
[2, 'name1','something',18],
[3, 'name10','something',5],
[5, 'name20','something',20]
]
Appreciate your help!
Thanks!
Just update the array indices of the required elements
In my test case, I changed the indices used in the script. The script used would be as follows:
function myFunction() {
var array = [
[2, 'name1', 'something', 15],
[3, 'name10', 'something', 5],
[5, 'name20', 'something', 20],
[2, 'name15', 'something', 3]
]
var result = Object.values(array.reduce((c, v) => {
if (c[v[0]]) c[v[0]][3] += v[3]; // Updated the indices
else c[v[0]] = v; // Updated the indices
return c;
}, {}));
console.log(result);
}
From here, index [0] represents the elements in the first column (2,3,5,2) while index [3] represents the elements in the last column (15,5,20,3). So basically, the script only processed the first and last columns to achieve your desired output.
Output

Filtering multi-dimensional array based on another array elements

I have two arrays in the code below - which matches is the main one and the other played which serves it is purpose for elements to filter out in the main array:
var matches = [[1,4],[3,1],[5,2],[3,4],[4,5],[2,1]];
var played = [2,5];
I need to filter out elements in matches based on played array, which means if there is any 2 or 5 in, then remove it altogether. Also the played array can be any length, min is 1.
Expected output should be
[[1,4],[3,1],[3,4]];
So I have tried this piece of code, but it doesn't yield the result I want.
var result = matches.map(x => x.filter(e => played.indexOf(e) < 0))
So anyway to achieve this?
You could check with some and exclude the unwanted arrays.
var matches = [[1, 4], [3, 1], [5, 2], [3, 4], [4, 5], [2, 1]],
played = [2, 5],
result = matches.filter(a => !a.some(v => played.includes(v)));
console.log(result);
While filtering, check that .every one of the subarray elements are not included in [2, 5]:
var matches = [[1,4],[3,1],[5,2],[3,4],[4,5],[2,1]];
var played = [2,5];
const result = matches.filter(
subarr => played.every(
num => !subarr.includes(num)
)
);
console.log(result);
Another way would be to create a Set of played to avoid iterating it again and again:
var matches = [[1,4],[3,1],[5,2],[3,4],[4,5],[2,1]];
var played = new Set([2,5]);
var out = matches.filter(a => !a.some(num => played.has(num)));
console.info(out)

understanding better a solution for finding permutations of a string - javascript

I'm trying to get a better understanding of recursion as well as functional programming, I thought a good practice example for that would be to create permutations of a string with recursion and modern methods like reduce, filter and map.
I found this beautiful piece of code
const flatten = xs =>
xs.reduce((cum, next) => [...cum, ...next], []);
const without = (xs, x) =>
xs.filter(y => y !== x);
const permutations = xs =>
flatten(xs.map(x =>
xs.length < 2
? [xs]
: permutations(without(xs, x)).map(perm => [x, ...perm])
));
permutations([1,2,3])
// [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
from Permutations in JavaScript?
by Márton Sári
I've delimited it a bit in order to add some console logs to debug it and understand what's it doing behind the scenes
const flatten = xs => {
console.log(`input for flatten(${xs})`);
return xs.reduce((cum, next) => {
let res = [...cum, ...next];
console.log(`output from flatten(): ${res}`);
return res;
}, []);
}
const without = (xs, x) => {
console.log(`input for without(${xs},${x})`)
let res = xs.filter(y => y !== x);
console.log(`output from without: ${res}`);
return res;
}
const permutations = xs => {
console.log(`input for permutations(${xs})`);
let res = flatten(xs.map(x => {
if (xs.length < 2) {
return [xs]
} else {
return permutations(without(xs, x)).map(perm => [x, ...perm])
}
}));
console.log(`output for permutations: ${res}`)
return res;
}
permutations([1,2,3])
I think I have a good enough idea of what each method iss doing, but I just can't seem to conceptualize how it all comes together to create [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
can somebody show me step by step what's going on under the hood?
To get all permuations we do the following:
We take one element of the array from left to right.
xs.map(x => // 1
For all the other elements we generate permutations recursively:
permutations(without(xs, x)) // [[2, 3], [3, 2]]
for every permutation we add the value we've taken out back at the beginning:
.map(perm => [xs, ...perm]) // [[1, 2, 3], [1, 3, 2]]
now that is repeated for all the arrays elements and it results in:
[
// 1
[[1, 2, 3], [1, 3, 2]],
// 2
[[2, 1, 3], [2, 3, 1]],
// 3
[[3, 1, 2], [3, 2, 1]]
]
now we just have to flatten(...) that array to get the desired result.
The whole thing could be expressed as a tree of recursive calls:
[1, 2, 3]
- [2, 3] ->
- [3] -> [1, 2, 3]
- [2] -> [1, 3, 2]
- [1, 3] ->
- [1] -> [2, 3, 1]
- [3] -> [2, 1, 3]
- [1, 2] ->
- [1] -> [3, 2, 1]
- [2] -> [3, 1, 2]
I've delimited it a bit in order to add some console logs to debug it
This can help of course. However keep in mind that simple recursive definitions can often result in complex execution traces.
That is in fact one of reasons why recursion can be so useful. Because some algorithms that have complicated iterations, admit a simple recursive description. So your goal in understanding a recursive algorithm should be to figure out the inductive (not iterative) reasoning in its definition.
Lets forget about javascript and focus on the algorithm. Let's see we can obtain the permutations of elements of a set A, which we will denote P(A).
Note: It's of no relevance that in the original algorithm the input is a list, since the original order does not matter at all. Likewise it's of no relevance that we will return a set of lists rather than a list of lists, since we don't care the order in which solutions are calculated.
Base Case:
The simplest case is the empty set. There is exactly one solution for the permutations of 0 elements, and that solution is the empty sequence []. So,
P(A) = {[]}
Recursive Case:
In order to use recursion, you want to describe how to obtain P(A) from P(A') for some A' smaller than A in size.
Note: If you do that, it's finished. Operationally the program will work out via successive calls to P with smaller and smaller arguments until it reaches the base case, and then it will come back bulding longer results from shorter ones.
So here is one way to write a particular permutation of an A with n+1 elems. You need to successively pick one element of A for each position:
_ _ ... _
n+1 n 1
So you pick an x ∈ A for the first
x _ ... _
n 1
And then you need to choose a permutation in P(A\{x}).
This tells you one way to build all permutations of size n. Consider all possible choices of x in A (to use as first element), and for each choice put x in front of each solution of P(A\{x}). Finally take the union of all solutions you found for each choice of x.
Let's use the dot operator to represent putting x in front of a sequence s, and the diamond operator to represent putting x in front of every s ∈ S. That is,
x⋅s = [x, s1, s2, ..., sn]
x⟡S = {x⋅s : s ∈ S}
Then for a non-empty A
P(A) = ⋃ {x⟡P(A\{x}) : x ∈ A}
This expression together with the case base give you all the permutations of elements in a set A.
The javascript code
To understand how the code you've shown implements this algortithm you need to consider the following
That code considers two base cases, when you have 0 or 1 elements, by writing xs.length < 2. We could have done that too, it's irrelevant. You can change that 2 into a 1 and it should still work.
The mapping corresponds to our operation x⟡S = {x⋅s : s ∈ S}
The without corresponds to P(A\{x})
The flatten corresponds to the ⋃ which joins all solutions.

javascript, looping through a multi-array to list the first element of the array

So I feel like I should be able to figure this one out, but for whatever reason, i've having some difficulty with it this morning.
I have an array with multiple arrays inside, and i want to loop through this big array and only list the first element in the smaller arrays.
so my array looks something like this
var array = [
[1, 2],
[1, 3],
[3, 4]
]
So, essentially I want to be able to list, (1, 1, 3). The problem for me is that when i try to approach any for loop, i am able to separate the arrays, but not able to list the first element in each smaller array.
I know this is pretty elementary, and even though i did take a look and did not find much, i do feel like this question has already been asked.
Any help with this would be wonderful.
Much thanks.
You can use map() for creating a modified array
var array = [
[1, 2],
[1, 3],
[3, 4]
];
var res = array.map(function(v) {
return v[0];
});
alert(res)
If you just want to list [1,1,3], then this might be enough:
array.map(function(item) {
return item[0];
});
Cheers,
Karol
How about :
var newArray = [];
array.forEach(function(el) {
newArray.push(el[0]);
});
console.log(newArray);
Just use for(...) instead of others for big array. It is fastest. You can see their speed difference in http://jsperf.com/find-first-from-multiple-arrray
var array = [
[1, 2],
[1, 3],
[3, 4]
], r = [];
for (var i = 0; i < array.length; i++) {
r.push(array[i][0]);
}
console.log(r);

Array.indexOf for list of lists is not working

I have a list of lists which comes from the server in ajax response has following structure:
var mapping = [ //response.mapping
["userOne", 1],
["userTwo", 2],
["userthree", 3],
["userfour", 4],
["personOne", 1],
["personTwo", 2],
["personOne", 3],
];
As the list will be constant forever, which will have only 7 elements at anytime. I want index of any of its element to update some DOM elements.
// Gives me any of list element which is random elm of the list `mapping`.
var captured_list_elm = process_mapping_list();
var status = mapping.indexOf(captured_list_elm);// getting always -1
Here I'm getting always -1 for status.
What could be the reason?
Why indexOf can not calculate its index?
What's the way to find it, get index through looping over list only?
Created a jsFiddle
NOTE - Actually it should be a json but someone out of our team had written it as a list of lists. I can not update it as of now because the code is in production.
Array.indexOf() uses strict equality (===) to find an element. The elements of mapping are arrays and two distinct arrays that happen to have the same elements are not ===. I suspect that process_mapping_list() is returning an array that looks like one of the elements of mapping but is not the element itself (just like your fiddle does).
You might need to write your own look-up function that uses a custom equality test. For such a test, take a look at this thread. Depending on the environment(s) you are targeting, you may be able to use findIndex() instead of indexOf(). That function allows you to supply your own testing function.
To confirm the answer #ted-hopp gave I forked your JSFiddle and slightly modified it. Basically what I did was to move the variable captured_list_elm to the top and add it as a value to the array. As you can see now Array.indexOf returns 4 which is the correct (zero-based) index:
var captured_list_elm = ["personOne", 1];
var mapping = [ //response.mapping
["userOne", 1],
["userTwo", 2],
["userthree", 3],
["userfour", 4],
captured_list_elm,
["personTwo", 2],
["personOne", 3],
];
var status = mapping.indexOf(captured_list_elm);
alert("status= "+status);
What you probably have to do is to add a for loop that iterates over your array and compares the values.
The problem is that you're comparing two arrays using indexOf. If you run your jsFiddle with this code, it'll return the right index because it's comparing the array itself, not the elements within it.
var status = mapping.indexOf(mapping[6]);
Here's a way to get around the === issue with indexOf...
Option 1:
create a temporary array with stringified arrays inside of it and then compare the stringified value
JSFiddle: http://jsfiddle.net/ceham967/1/
.
var mapping = [ //response.mapping
["userOne", 1],
["userTwo", 2],
["userthree", 3],
["userfour", 4],
["personOne", 1],
["personTwo", 2],
["personOne", 3],
];
var jsonMapping = [];
for (var i = 0; i < mapping.length; i++) {
jsonMapping.push(JSON.stringify(mapping[i]));
}
var captured_list_elm = ["personOne", 1];
var status = jsonMapping.indexOf(JSON.stringify(captured_list_elm));
alert("status= "+status);
Option 2
For loop comparison
JSFiddle: http://jsfiddle.net/ceham967/2/
.
var mapping = [ //response.mapping
["userOne", 1],
["userTwo", 2],
["userthree", 3],
["userfour", 4],
["personOne", 1],
["personTwo", 2],
["personOne", 3],
];
var findIndex = function (hayStack, needle) {
for (var i = 0; i < hayStack.length; i++) {
if(hayStack[i][0] === needle[0] && hayStack[i][1] === needle[1]) {
return i;
}
}
return -1;
};
var captured_list_elm = ["personOne", 1];
var status = findIndex(mapping, captured_list_elm);
alert("status= "+status);

Categories