react-native redux nested array reducer - javascript

I am learning to write reducers for arrays. For example, one of the reducers changes array elements from integers to arrays.
Original state:
[0, 3, 5, 3, 9, 8]
Action:
case ADD_NEST:
return state.map(i => [i, action.payload]);
New state:
[[0, 0], [3, 0], [5, 0], [3, 0], [9, 0], [8, 0]]
I'm trying to write a reducer that would change the second element of sub-arrays based on the condition of the first one. (eg, if the first element of the subarray is greater than 3, change the second element to 1).
[[0, 0], [3, 0], [5, 1], [3, 0], [9, 1], [8, 1]]
so far I have (not much as I'm stuck):
case SET_BIT:
return state.map(i => (i[0] > 3 ? ??? : i));
Thank you for advice!

Like this?
case SET_BIT:
return state.map(i => (i[0] > 3 ? [i[0], i[1] + 1] : i));
Although, that's a bit weird/dangerous. What happens if SET_BIT gets dispatched when your state of that reducer is still a flat array? Then the above code will crash. Then you would have to do something like:
case SET_BIT:
return state.map(i => (
Array.isArray(i) && i[0] > 3
? [i[0], i[1] + 1]
: i
));
I don't know the details of what you are trying to do here, but generally speaking I think it's best to keep the structure of the state of a reducer consistent. I tend to avoid nested structures in the state of my redux store because I try to keep the state of my redux store as normalized as I can. That makes reducers a lot easier to maintain. If I need to nest stuff for my views I usually do that in the selectors.
But again, I lack context, so not sure if any of this advice is relevant to you. :-)

Related

How to use reduce method within map method to add numbers

Not sure if I am overcomplicating things but I am trying to get the sum of all the numbers inside this array of arrays:
const frames = [
[2, 0], [4, 2], [6, 0], [2, 4], [1, 5], [7, 0], [5, 2], [7, 0], [2, 6], [8, 1]
]
I am practising using map and reduce to do so:
const score = (frames) =>{
console.log(frames)
let addedScores = frames.map(frame.reduce((previousValue, currentValue) => previousValue + currentValue))
console.log(addedScores)
}
But currently getting this error:
TypeError: 2,04,26,02,41,57,05,27,02,68,1 is not a function
at Array.map (<anonymous>)
at score (/Users/x/Desktop/Programming/devacademy/bootcamp/week1/preparation/bowling-kata/game.js:8:28)
at Object.<anonymous> (/Users/x/Desktop/Programming/devacademy/bootcamp/week1/preparation/bowling-kata/game.js:17:1)
Here is a fiddle version.
Any advice and explanation would be greatly appreciated
You are almost there on this one! If you look at the stack trace for the error you are facing, you will see that an error is thrown by Array.map function, and namely that "stuff" (i.e 2,04,26,02,41,57,05,27,02,68,1) is "not a function".
The map higher-order function expects a function that it will map accross the elements of frames.
What you want is something like this:
//...
let addedScores = frames.map((frame) => frame.reduce((previousValue, currentValue) => previousValue + currentValue))
//...
Here I have only converted your addedScores expression to pass an anonymous function: (frame) => { ... } to the map function.
Hope this helps!
The resulting shape for addedScores would be: [2, 6, 6, 6, 6, 7, ...], which is the sum of each pair of numbers in frames.

Array sort and value change at the same time

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.

Best datastructure in javascript for a certain relationship

I have already posted my question here:
Best datastructure in javascript for certain relationship
I try now to reformulate my problem and make it more clear.
Let us assume I have a table (for instance in an .csv file) with two columns and a few thousand rows. In the first column are arrays with 5 to 8 integers, eachs either 0, 1, 2 or 3. In the second I have an array of arrays containing two integers. It may look like
[3, 1, 2, 2, 0, 0, 2] | [[4, 50], [5, 50]]
[2, 2, 0, 1, 1, 0, 0, 1] | [[2, 50], [5, 100], [6, 50]]
.
.
.
[0, 2, 0, 0, 3] | [[0, 10], [2, 10], [3, 10]]
Now I want to load this table in javascript to store it such that, given for example the array [2, 2, 0, 1, 1, 0, 0, 1] , the retrieval of the array [[2, 50], [5, 100], [6, 50]] is very fast. Which is the best way / datastructure to store this table / relationship for a very fast retrieval?
Thanks in advance.
Edit:
The relationship between the input and output is as follows: For every zero in the input there is an array with two integers in the output, the first integer is the position of the zero. The second interger is a certain score for the input. The calculation of this score is a bit complex, but I think it is not of interest for this question. We can simply assume that this table is given.
You'll want to use a Map.
While in theory it can use array objects as the key, it would compare them by identity, you probably are looking for lookup by value though. The simplest workaround for that is to use a string representation of the array as the key, e.g. JSON.stringify(arr) or arr.join('|').
const table = [
[[3, 1, 2, 2, 0, 0, 2], [[4, 50], [5, 50]]],
[[2, 2, 0, 1, 1, 0, 0, 1], [[2, 50], [5, 100], [6, 50]]],
[[0, 2, 0, 0, 3], [[0, 10], [2, 10], [3, 10]]],
];
const map = new Map(table.map(([key, val]) => [key.join('|'), val]));
console.log(map.get([0, 2, 0, 0, 3].join('|')));
Given that you are effectively wanting to prioritise the retrieve of key/value pairs, a hash map should be the quickest solution. Plain js objects offer an in-built hashmap option (which is suitable as long as your keys are unique.
You should consider the js Map object if you wish to use Array objects (which may contain the same values) as keys.
e.g.
var arrayA = [1,2,3]
var arrayB = [1,2,3]
var map = new Map()
map2.set(arrayA, 'first')
map2.set(arrayB, 'second')
map2.get(arrayA) >> 'first'
map2.get(arrayB) >> 'second'

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.

Spread Syntax with Map and Filter

I found this interesting problem and wanted to share with you guys.
The question is :
[...[0,1,...[-1,0,1].map((x)=> x+1)].filter((x)=>x)),7]
I easily solved the first section upto the filter as [0,1,(-1+1),(0+1),(1+1)] = [0,1,0,1,2].
I was surprised to find the 7 hanging at the end. I thought it was some typo but copying the problem into the console gave me [1,1,2,7]. I couldn't quite understand 2 things.
why were the 0's left out of filter
what's the 7 doing there
The first operation here is Array#map [-1, 0, 1].map(x => x + 1) which basically adds 1 to each element, returning [0, 1, 2] array.
Next one is Array#filter operation, [0, 1, ...[0, 1, 2]].filter(x => x) which actually returns a new array, without every falsy value (false, 0, undefined, null, "") out of the array.
The last operation looks like [...[1, 1, 2], 7] and gets rid of the nested array with the spread operator returning [1, 1, 2, 7].
[...[0,1,...[-1,0,1].map((x)=> x+1)].filter((x)=>x),7] broken down:
[-1,0,1].map((x)=> x+1) // [0,1,2]
[0,1,...[-1,0,1].map((x)=> x+1)] // [0,1,0,1,2]
[0,1,...[-1,0,1].map((x)=> x+1)].filter((x)=>x) // [1,1,2]
[...[0,1,...[-1,0,1].map((x)=> x+1)].filter((x)=>x),7] // [1,1,2,7]
this part [-1,0,1].map((x)=> x+1) results in this list [0,1,2] then this part [0,1,...[-1,0,1].map((x)=> x+1)] results in [0,1,1,2] which after the filter part drops the 0 so it results into [1,1,2], finally the last element of the list is 7. So, altogether the result is [1,1,2,7]
The code evaluates in the following steps:
[...[0, 1, ...[-1, 0, 1].map((x)=>x+1)].filter((x)=>x)), 7] // map
[...[0, 1, ...[(x=>x+1)(-1), (x=>x+1)(0), (x=>x+1)(1)]].filter((x)=>x)), 7] // function application
[...[0, 1, ...[0, 1, 2]].filter((x)=>x)), 7] // spread
[...[0, 1, 0, 1, 2].filter((x)=>x)), 7] // filter
[...[...(x=>x)(0)?[0]:[], ...(x=>x)(1)?[1]:[], ...(x=>x)(0)?[0]:[], ...(x=>x)(1)?[1]:[], ...(x=>x)(2)?[2]:[]], 7] // function application
[...[...0?[0]:[], ...1?[1]:[], ...0?[0]:[], ...1?[1]:[], ...2?[2]:[]], 7] // conditional
[...[...[], ...[1], ...[], ...[1], ...[2]], 7] // spread (from filter)
[...[1, 1, 2], 7] // spread
[1, 1, 2, 7]

Categories