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'
Related
I have an array of arrays. How can I get an array with a nested array whose elements have a unique order?
What I have:
[[1, 2], [1, 2, 3], [3, 4]]
Expected Output:
[[1, 2, 3], [3, 4]]
I think, that I can format to JSON, and get my result with filter and indexOf ,I have tried this:
var unique = x2.map(ar=>JSON.stringify(ar).replace(/[\[\]']+/g,''))
.filter((itm, idx, arr) => arr.indexOf(itm) === idx);
Here is my try, I first sorted the array by its length then applied filter and match the index position by making use of every and includes. Here is an example:
var example = [[1, 2, 35, 7], [1, 2, 3], [35, 7], [3, 4], [4]];
var result = example.sort((a,b)=>b.length-a.length).filter((k,i,self)=>self.findIndex(p=>k.every(l=>p.includes(l)))==i);
console.log(result);
I hope this helps.
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. :-)
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]
is there any way to make javascript array to initialize all the values to 0 without iteration like as shown below
var array = [1, 2, 3, 4, 5];
to
[0, 0, 0, 0, 0]
You could, in compliant browsers, use Array.prototype.fill():
var array = [1, 2, 3, 4, 5];
array.fill(0); // [0, 0, 0, 0, 0]
References:
Array.prototype.fill().
Array.apply(null, new Array(5)).map(Number.prototype.valueOf, 0))
Useful article Initializing arrays
Its a bit tricky. But it works
var array = [1, 2, 3, 4, 5];
array = JSON.parse(JSON.stringify(array).replace(/(\d+)/g,0)); // Returns [0,0,0,0,0]
i guess you don't need eval if you use JSON.parse() to build the empties and splice() to mutate the existing array instead of just making a new array full of zeros:
var r=[1, 2, 3, 4, 5];
[].splice.apply(r,
[0, r.length].concat(
JSON.parse("[0"+new Array(r.length).join(",0")+"]")
));
alert(r); // shows: "0,0,0,0,0"
Answers based on map()/fill() will not affect the orig array as desired, but those solutions could use splice like the above answer to do so, the only difference then is how one build the zero-filled array.
EDIT: kudos to Gilsha, i was working on an eval-based answer when you reminded me that JSON would be enough.
I'm retrieving some data and the data looks like this:
1, 2, 3, 4, 5
6, 7, 8, 9, 10
11, 12, 13, 14, 15
I want it to look like this
[
[[1],[2],[3],[4],[5]],
[[6],[7],[8],[9],[10]],
[[11],[12],[13],[14],[15]]
]
So that I may address the array like a matrix, data[0][1] would be "2".
Through this answer, it's almost there, but not quite. I'm having trouble getting to look like what I want.
How about this, assuming this accurately represents your input data:
var data = "1,2,3,4,5\n6,7,8,9,10\n11,12,13,14,15";
var matrix = data.split('\n').map(function(val) {
return val.split(',');
});
Note that your specified output is probably not what you meant. Each number should probably not be its own single-item array. Instead, the code above produces:
[
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 1]
]
Which means matrix[0][1] would return 2, as opposed to having to do matrix[0][1][0]
Edit: As noted in the comments, I've left it up to you to ensure this fits your browser-support needs. This also goes for every other line of JS you ever write...
NOTE - If you need to iterate through an array use a simple for, and not a for..in
for..in returns the items in no guaranteed order which is probably not what you want when working with an array
for..in returns not the just the array elements, but anything added to the Array prototype (meaning if you use a traditional for loop you can be completely confident the code will work regardless of what external libraries may be included on the page. No need to worry that some other coder has added properties/methods to Array.prototype)
If \n is the line separator and , is the item seperator within a line, you can use something like:
/* assuming data is already filled like:
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
*/
var arr = data.split("\n"), arr2 = [];
for(var i = 0; i < arr.length; i++) {
if(arr[i] != '') arr2.push(arr[i].split(','));
}
console.log(arr2);
/* arr2 will be like:
[
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
]
*/
var data = '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15'.split(',');
var matrixData = [];
while (data.length > 0) {
matrixData.push(data.splice(0, 5));
}
document.write(matrixData[0][1]);
Edit: If you get the data as a simple array of numbers