Related
I've written a a function which takes score as parameter and should return the letter grade.
There are some conditions to be followed while writing the code. ie: return 'A' if 25 < score <= 30 return 'B' if 20 < score <= 25 and so on. So I wanted to do this by omitting a whole lot of if-else's. As I'm new to javascript this is all I could come up with:
// This function takes Nested arrays and a single number,
// which checks its availability in
// the inside array and then return the index of the array
function my_index(arr, score) {
for (const [index, elem] of arr.entries()) {
if (elem.includes(score)) {
return index;
}
}
}
// function to get letter grade
function getGrade(score) {
let grade;
var gradeDict = {
'A': [26, 27, 28, 29, 30],
'B': [21, 22, 23, 24, 25],
'C': [16, 17, 18, 19, 20],
'D': [11, 12, 13, 14, 15],
'E': [6, 7, 8, 9, 10],
'F': [0, 1, 2, 3, 4, 5]
}
var keys = Object.keys(gradeDict);
var values = [Object.values(gradeDict)]
grade = keys[my_index(values, score)]
return grade;
}
The first function works fine. It returns the index of nested array. But the main function getGrade happens to return 'Undefined'. Can't think of a better solution than this to reduce a bunch of ugly if-elses.
var question = {
'1st': 'Can anybody help me get this done?',
'2nd': 'Is there any better way to do this?'
}
Is there a better way to write this?
I'd do:
function getLetterGrade(score) {
return ['F', 'F', 'E', 'D', 'C', 'B', 'A'][Math.ceil(score / 5)];
}
(F occurs twice because more scores map to F than to other grades)
It may be a bit cryptic, but is easier to tune should the possible score ever change.
Remove the outer [] array of the Object.values. Object.values already returns values in array.
from
var values = [Object.values(gradeDict)];
to
var values = Object.values(gradeDict);
working example:
function my_index(arr, score) {
for (const [index, elem] of arr.entries()) {
if (elem.includes(score)) {
return index;
}
}
}
function getGrade(score) {
let grade;
var gradeDict = {
A: [26, 27, 28, 29, 30],
B: [21, 22, 23, 24, 25],
C: [16, 17, 18, 19, 20],
D: [11, 12, 13, 14, 15],
E: [6, 7, 8, 9, 10],
F: [0, 1, 2, 3, 4, 5],
};
var keys = Object.keys(gradeDict);
var values = Object.values(gradeDict);
grade = keys[my_index(values, score)];
return grade;
}
console.log(getGrade(5));
console.log(getGrade(25));
Alternate solution
function getGrade(score) {
let grade;
var gradeDict = {
A: [26, 27, 28, 29, 30],
B: [21, 22, 23, 24, 25],
C: [16, 17, 18, 19, 20],
D: [11, 12, 13, 14, 15],
E: [6, 7, 8, 9, 10],
F: [0, 1, 2, 3, 4, 5],
};
for (let key in gradeDict) {
if (gradeDict[key].includes(score)) return key;
}
return "Not found";
}
console.log(getGrade(5));
console.log(getGrade(25));
I like the ceil solution proposed earlier, but here is another general solution in case it's helpful:
function grade(score) {
if (score < 0 || score > 30) throw RangeError(`Score ${score} out of range`);
for (let ii = 5; ii >= 0; ii--) {
if (score > 5*ii) return String.fromCharCode(70 - ii);
}
return 'F';
}
console.log(0, '=>', grade(0)) // F
console.log(4, '=>', grade(4)) // F
console.log(6, '=>', grade(6)) // E
console.log(10, '=>', grade(10)) // E
console.log(27, '=>', grade(27)) // A
console.log(30, '=>', grade(30)) // A
We have an array of arrays like this:
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14]
];
There may be duplicate elements in each array and that's fine.
But I'm after a proper solution to remove duplicate elements in each set comparing to lower sets!
So as we have a 0 in the first array and the last array, we should consider the 0 in last one a duplication and remove it...
the desired result would be:
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[12],
[14]
It's a confusing issue for me please help...
You could collect the values in an object with index as value, and filter for values who are at the same index.
const
arrays = [[0, 1, 2, 3, 4, 4, 4, 4], [5, 6, 7, 8, 9, 10, 11, 11], [2, 7, 10, 12], [0, 7, 10, 14]],
seen = {},
result = arrays.map((array, i) => array.filter(v => (seen[v] ??= i) === i));
result.forEach(a => console.log(...a));
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[4, 4, 5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14]
]
let filtered = arrays.map((row, i) => {
// concat all previous arrays
let prev = [].concat(...arrays.slice(0, i))
// filter out duplicates from prev arrays
return row.filter(r => !prev.includes(r))
})
console.log(filtered)
We can do this using Array#reduce and maintain a seen Set, which will have all visited numbers from each array.
Once you iterate over an array you push all visited elements in the seen Set, then push a new array filtered by the elements not in the seen Set:
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14]
];
const removeDupsInSibling = (arr) => {
let seen = new Set();
return arr.reduce((acc, a)=> {
const f = a.filter(v => !seen.has(v));
seen = new Set([...seen, ...a]);
acc.push(f);
return acc;
}, []);
}
console.log(removeDupsInSibling(arrays));
There are plenty of inefficient ways to do this, but if you want to do this in O(n), then we can make the observation that what we want to know is "which array a number is in". If we know that, we can run our algorithm in O(n):
for every element e in array at index i:
if index(e) == i:
this is fine
if index(e) < i:
remove this e
So let's just do literally that: we allocate an object to act as our lookup, and then we run through all elements:
const lookup = {};
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14]
];
const reduced = arrays.map((array, index) => {
// run through the elements in reverse, so that we can
// safely remove bad elements without affecting the loop:
for(let i=array.length-1; i>=0; i--) {
let value = array[i];
let knownIndex = (lookup[value] ??= index);
if (knownIndex < index) {
// removing from "somewhere" in the array
// uses the splice function:
array.splice(i,1);
}
}
return array;
});
console.log(reduced);
For an alternative, where the loop+splice is taken care of using filter, see Nina's answer.
Simple, clean and high performance solution:
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14]
];
const duplicates = {};
const answer = arrays.map( (array, level) => {
return array.filter( el => {
if ( duplicates[el] < level ) {
// return nothing; fine
} else {
duplicates[el] = level;
return el
}
})
});
console.log(JSON.stringify(answer))
here is on-liner and less-readable form:
const d = {}, arrays = [ [0, 1, 2, 3, 4, 4, 4, 4], [5, 6, 7, 8, 9, 10, 11, 11], [2, 7, 10, 12], [0, 7, 10, 14]];
const answer = arrays.map((a,l)=> a.filter(el=> d[el]<l ? 0 : (d[el]=l,el)));
console.log(JSON.stringify(answer))
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14],
];
const output = arrays.reduce(
({ output, set }, current, i) => {
output[i] = current.filter((num) => !set.has(num));
[...new Set(output[i])].forEach((num) => set.add(num));
return { output, set };
},
{ output: [], set: new Set() }
).output;
console.log(output);
Gets the exact output you want:
[
[
0, 1, 2, 3,
4, 4, 4, 4
],
[
5, 6, 7, 8,
9, 10, 11, 11
],
[ 12 ],
[ 14 ]
]
If my Array1 is
Array1 = [1,2,3,4,5,6,7,8,9,10]
the Result should be the same as Combined_Array= [1,2,3,4,5,6,7,8,9,10]
if i got
Array2=[11,12,13,14,15,16,17,18,19,20]
the Resut should be Combined_Array =[1,2,3,4,5,11,12,13,14,15]
and if again i got
Array3=[21,22,23,24,25,26,27,28,19,30]
The Combined_array = [1,2,3,11,12,13,21,22,23,24]
and so on , Doesnt matter how much Array's i want that it should give me a Combined_Array from all the different Array with Fixed Length
Need a Function to make this work .
You could take a closure over the collected arrays and retuen an array of the parts which are difined by the count of arrays.
const
getCombined = (a) => {
const allArrays = [];
return (b => {
allArrays.push(b);
let i = 0,
p = Math.floor(10 / allArrays.length),
result = [];
while (i < allArrays.length) result.push(...allArrays[i++].slice(0, p));
while (result.length < 10) result.push(allArrays[allArrays.length - 1][p++]);
return result;
});
};
var c = [],
add = getCombined(c);
c = add([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
console.log(...c); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
c = add([11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
console.log(...c); // [1, 2, 3, 4, 5, 11, 12, 13, 14, 15]
c = add([21, 22, 23, 24, 25, 26, 27, 28, 29, 30]);
console.log(...c); // [1, 2, 3, 11, 12, 13, 21, 22, 23, 24]
You need to consider many corner cases (if result array length exceeds given arrays count, if given arrays length differs and so on).
This will work for the simple scenario:
const arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arr2 = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
const arr3 = [21, 22, 23, 24, 25, 26, 27, 28, 19, 30];
const combineArrays = (arr, length) => {
let elementsCount = Math.floor(length / arr.length);
const result = arr.reduce((acc, el) =>
acc.concat(el.slice(0, elementsCount)), []);
while (result.length < length)
result.push(...arr.pop().slice(elementsCount, ++elementsCount));
return result;
};
const result1 = combineArrays([arr1], 10); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const result2 = combineArrays([arr1, arr2], 10); // [1, 2, 3, 4, 5, 11, 12, 13, 14, 15]
const result3 = combineArrays([arr1, arr2, arr3], 10); // [1, 2, 3, 11, 12, 13, 21, 22, 23, 24]
i'm trying to understand the following code? and why i get the following output
for (let [i, j, ...x] of [
[2, 3, 4, 5, 10, 11, 12, 13].filter(e => e > 5)
]) {
console.error(x)
}
expected output [10, 11, 12, 13] actual output x = [12, 13]
for(let [i, j, ...x] of [[2, 3, 4, 5, 10, 11, 12, 13].filter(e => e > 5 )]) {
console.error(x)
}
First you need to look at [2, 3, 4, 5, 10, 11, 12, 13].filter(e => e > 5 )
which returns: [10, 11, 12, 13].
Afterwards [i, j, ...x] = [10, 11, 12, 13]will get applied. This means, i = 10, j = 11 and x takes the rest which means x = [12, 13].
We print x and voila, it's [12, 13].
But what about [[10, 11, 12, 13]]? First see the snippet below:
let [k, l, ...y] = [2, 3, 4, 5, 10, 11, 12, 13]
console.log(k,l,y)
let [i, j, ...x] = [[2, 3, 4, 5, 10, 11, 12, 13]]
console.log(i,j,x)
So with a single bracket we get the expected results so why in the given code we have double brackets and it works just fine?
Well, see the following snippet and compare:
for (let [i, j, ...x] of [[2, 3, 4, 5, 10, 11, 12, 13]]) {
console.log(i,j,x)
}
This works just fine but what happens when we loop with single brackets?
for (let [i, j, ...x] of [2, 3, 4, 5, 10, 11, 12, 13]) {
console.log(i,j,x)
}
We get an error! But why?
for...of gets us the inner values of the array of array via its internal iterator. It gets us the 'next' element from our outer array which is our inner array. That's why we only ever got a single iteration in our loop anyway since there is only one 'next'!
On that single element we are iterating we apply the deconstructing syntax and print the result. It's a lot of hot air over nothing, basically.
You Just need to remove i,j
for (let [...x] of [
[2, 3, 4, 5, 10, 11, 12, 13].filter(e => e > 5)
]) {
console.error(x)
}
if you want to get numbers that are larger than 5 , you can use this code
for (let [i, j, ...x] of [
[2, 3, 4, 5, 10, 11, 12, 13].filter(e => e > 5)
]) {
console.error(x)
}
var numberArray= [2, 3, 4, 5, 10, 11, 12, 13];
var numberBiggerThanFive = [];
for(i in numberArray){
if(i > 5 ){
numberBiggerThanFive.push(i)
}
}
console.log(numberBiggerThanFive);
I currently have the following array set up:
var TicketInfo =
{
t1: {
1: [7, 12, 35,39,41, 43],
2: [7, 15, 20,34,45, 48],
3: [3, 7, 10, 13, 22, 43],
4: [2, 4, 5,23,27, 33]
},
t2: {
1: [10, 12, 17,44,48, 49],
2: [13, 15, 17, 18, 32, 39],
3: [16, 17, 20, 45, 48, 49],
4: [6, 16, 18, 21, 32, 40]
}
}
What I want to do is iterate through these to bring back the arrays under.
As a test I've tried something like this:
for(t in TicketInfo["t1"])
{
i++;
Write(t.i);
}
But it's obviously not working how I want it to.
Any ideas?
I want to be able to output the arrays like [7, 12, 35,39,41, 43]
Thanks
var TicketInfo =
{
t1: {
1: [7, 12, 35,39,41, 43],
2: [7, 15, 20,34,45, 48],
3: [3, 7, 10, 13, 22, 43],
4: [2, 4, 5,23,27, 33]
},
t2: {
1: [10, 12, 17,44,48, 49],
2: [13, 15, 17, 18, 32, 39],
3: [16, 17, 20, 45, 48, 49],
4: [6, 16, 18, 21, 32, 40]
}
}
for(var j in TicketInfo )
{
for(var p in TicketInfo[j] )
{
for(var i = 0; i < TicketInfo[j][p].length; i++ )
{
console.log(TicketInfo[j][p][i]);
}
}
}
http://jsfiddle.net/J6rTj/
If you're here from google trying to find a way to do a quick print for debugging, here's a one liner for you:
console.log(myArray.join("\n"))
Example:
var myArray = [[1,2,3],[4,5,6],[7,8,9]];
console.log(myArray.join("\n"));
Output:
1,2,3
4,5,6
7,8,9
Example with proper brackets:
var myArray = [[1,2,3],[4,5,6],[7,8,9]];
console.log("[[" + myArray.join("],\n[") + "]]");
Output:
[[1,2,3],
[4,5,6],
[7,8,9]]
Answer to OP's question:
obj = {
1: [7, 12, 35,39,41, 43],
2: [7, 15, 20,34,45, 48],
3: [3, 7, 10, 13, 22, 43],
4: [2, 4, 5,23,27, 33],
}
var keys = Object.keys(obj);
keys.sort();
console.log(keys);
var listFromObj = []
for (var i = 0; i < keys.length; i++) {
if (obj.hasOwnProperty(keys[i])) listFromObj.push(obj[keys[i]]);
}
console.log("[" + listFromObj.join("]\n[") + "]");
Output:
[7,12,35,39,41,43]
[7,15,20,34,45,48]
[3,7,10,13,22,43]
[2,4,5,23,27,33]
The syntax is TicketInfo["t1"]["1"][0].
That example will give you 7.
TicketInfo["t1"]["1"] will give you the array you're after at the base of your question.
In your code t just represents the key.
Try following code:
var TicketInfo =
{
t1: {
1: [7, 12, 35,39,41, 43],
2: [7, 15, 20,34,45, 48],
3: [3, 7, 10, 13, 22, 43],
4: [2, 4, 5,23,27, 33]
},
t2: {
1: [10, 12, 17,44,48, 49],
2: [13, 15, 17, 18, 32, 39],
3: [16, 17, 20, 45, 48, 49],
4: [6, 16, 18, 21, 32, 40]
}
}
for(t in TicketInfo["t1"])
{
i++;
console.log(TicketInfo["t1"][t]);
}
Do I understand that you want to output entire table in order? Since you use objects on t1/t2 level, you'll have to do extra steps for that.
First, see if you can simply replace objects with real arrays:
var TicketInfoArrays = {
t1: [
[7, 12, 35,39,41, 43],
[7, 15, 20,34,45, 48],
[3, 7, 10, 13, 22, 43],
[2, 4, 5,23,27, 33]
]
}
var t1 = TicketInfoArrays.t1
for(var idx = 0, len = t1.length; idx<len; idx++){
var line = idx+": ["
var nested = t1[idx]
for(var idx2 = 0, len2 = nested.length; idx2<len2; idx2++){
line += ((idx2 > 0 ? ', ':'') + nested[idx2])
}
console.log(line + ']')
}
If that's somehow impossible, but you sure that keys in those objects always start at some specific number and go ascending without gaps, you can simply itreate over properties until you hit empty element:
var TicketInfo = {
t1: {
1: [7, 12, 35,39,41, 43],
2: [7, 15, 20,34,45, 48],
3: [3, 7, 10, 13, 22, 43],
4: [2, 4, 5,23,27, 33]
}
}
var t1 = TicketInfo.t1
var idx = 1
var nested
while(nested = t1[idx]){
var line = idx+": ["
var nested = t1[idx]
for(var idx2 = 0, len2 = nested.length; idx2<len2; idx2++){
line += ((idx2 > 0 ? ', ':'') + nested[idx2])
}
console.log(line + ']')
idx++
}
Finally, if you can't guarantee even that, you will have to manually collect all keys, sort them and then iterate over this sorted list.
var TicketInfoUnordered = {
t1: {
8: [7, 12, 35,39,41, 43],
20: [7, 15, 20,34,45, 48],
45: [3, 7, 10, 13, 22, 43],
3: [2, 4, 5,23,27, 33]
}
}
var t1 = TicketInfoUnordered.t1
var keys = []
for(key in t1){
if(t1.hasOwnProperty(key)){ keys.push(key) }
}
keys.sort(function(a, b){ return a - b })
for(var idx = 0, len = keys.length; idx<len; idx++){
var line = keys[idx]+": ["
var nested = t1[keys[idx]]
for(var idx2 = 0, len2 = nested.length; idx2<len2; idx2++){
line += ((idx2 > 0 ? ', ':'') + nested[idx2])
}
console.log(line + ']')
}