Related
I have an object list to store indexes just like that:
const initialIndexes = {
0: [0,1,2],
1: [0,1]
}
At this point I have a highlightedResultIndex variable. It gives an index like this:
highlightedResultIndex = 0 - case 1
highlightedResultIndex = 4 - case 2
highlightedResultIndex = 2 - case 3
...
And I finally try to get the following results by highlightedResultIndex
For the case 1:
result = {
0: 0, // index from initialIndexes
1: -1
}
For the case 2:
result = {
0: -1,
1: 1 // index from initialIndexes
}
For the case 3:
result = {
0: 2 // index from initialIndexes
1: -1
}
Maybe there is an easy method or there may be a certain algorithm for this, but I didn't know how to research it so I wanted to write it here. I would be glad if you help.
EDIT:
Let me put here some of examples
// This is data from the server side.
const initialIndexes = {
0: [0,1,2,3],
1: [0,1,2],
2: [0,1,2],
3: [0,1,2,3,4]
}
// So, I need to index object like this by highlightedResultIndex variable
// highlightedResultIndex = 0
{
0:0,
1:-1,
2:-1,
3:-1
}
// highlightedResultIndex = 6
{
0: -1,
1:2,
2:-1,
3:-1
}
// highlightedResultIndex = 10
{
0: -1,
1:-1,
2:-1,
3:0
}
You could take the wanted index value and reduce it by the lenght of the arrays until it fits into an array.
const
initialIndexes = { 0: [0, 1, 2, 3], 1: [0, 1, 2], 2: [0, 1, 2], 3: [0, 1, 2, 3, 4] },
getIndices = n => Object.fromEntries(Object
.entries(initialIndexes)
.map(([key, array]) => {
const value = n >= 0 && n < array.length
? array[n] // or just n
: -1;
n -= array.length;
return [key, value];
})
);
console.log(getIndices(0)); // { 0: 0, 1: -1, 2: -1, 3: -1 }
console.log(getIndices(6)); // { 0: -1, 1: 2, 2: -1, 3: -1 }
console.log(getIndices(10)); // { 0: -1, 1: -1, 2: -1, 3: 0 }
.as-console-wrapper { max-height: 100% !important; top: 0; }
Write a function - countNumbers It should accept string with different symbols and return an object which contains counts of each number.
Tip: consider reusing makeNumber function.
My solution is not full, what should i do the next?
function countNumbers (string) {
let numbers = [];
for (let i = 0; i < string.length; i++) {
if (!isNaN(parseInt(string[i]))){
numbers.push([string[i]])
}
}
return numbers.join('');
};
for example: countNumbers('erer384jj4444666888jfd123');
// => {'1': 1, '2': 1, '3': 2, '4': 5, '6': 3, '8': 4}
countNumbers('jdjjka000466588kkkfs662555');
// => {'0': 3, '2': 1, '4': 1, '5': 4, '6': 4, '8': 2}
You can use an object instead of an array, and check if the property already exists. If it does then add 1, else set it to start with 1.
In your code you return a string with return numbers.join(''); but in this case your can return the object instead.
function countNumbers(string) {
let numbers = {};
for (let i = 0; i < string.length; i++) {
let val = string[i];
if (!isNaN(parseInt(val))) {
val in numbers ? numbers[val]++ : numbers[val] = 1;
}
}
return numbers;
}
console.log(countNumbers('erer384jj4444666888jfd123'));
console.log(countNumbers('jdjjka000466588kkkfs662555'));
Or as pointed out by #secan as an alternative solution you can use a pattern [0-9] with the global flag /g to get the digits from the string.
const countNumbers = str => {
const counterObj = {};
str.match(/[0-9]/g).forEach(
s => counterObj.hasOwnProperty(s) ? counterObj[s] += 1 : counterObj[s] = 1
);
return counterObj;
}
console.log(countNumbers('erer384jj4444666888jfd123'));
console.log(countNumbers('jdjjka000466588kkkfs662555'));
let conditon = false
const test = [2, 0, 3, 4, 5, 6, 7]
for (let i = 0; i < 10; i++) {
for (let j = 0; j < test.length; j++) {
if (0 !== test[j]) {
conditon = true;
break;
}else{
conditon = false;
break;
}
}
console.log(conditon)
}
In this loop it console.log true but it should print false when it finds 0 in an array
You are continuously setting condition to true, because e.g. 0 !== 2 evaluates to true. This is the case for every element, except 0. 0 !== 0 which evaluates to false. You need to put an else check in there and set condition to false, then break out so that it doesn't continue and override your value again by setting condition back to true for the next iterations.
let condition = false;
const test = [2, 0, 3, 4, 5, 6, 7]
for (let i = 0; i < 10; i++) {
for (let j = 0; j < test.length; j++) {
if (0 !== test[j]) {
conditon = true;
} else {
conditon = false;
break;
}
}
console.log(conditon)
// Comment this part out if you want it to continue looping without immediately stopping.
// Otherwise the loop ends once it hits 0.
if(!condition)
break;
}
This is not the best way to do this, mind you... I'm just providing you an example on why your code works the way it does.
Here's a simplified version, which you can examine to see how it works, and which you can use as a template for a more complicated version if desired.
let condition;
const nums = [2, 0, 3, 4, 5, 6, 7];
for(let i = 0; i < 2; i++){
for (let num of nums) {
condition = (num !== 0);
console.log(num, condition);
}
console.log("\n--end of outer loop--\n\n");
}
Edit:
From your comment, I gleaned that after each trip through the outer loop, you want to report if any value in the array was zero. If this is what you're looking for, you'd do something like this:
const nums = [2, 0, 3, 4, 5, 6, 7];
for(let i = 0; i < 2; i++){
let noZerosFound = true;
console.log("checking: " + nums);
for (let num of nums) {
if(num === 0){
noZerosFound = false;
// Can include a `break` statement here for better performance
}
}
console.log("noZerosFound: " + noZerosFound);
console.log("\n");
}
And JavaScript arrays also provide some useful built-in methods for this kind of situation. So if you want, you could simply do:
const nums = [2, 0, 3, 4, 5, 6, 7];
for(let i = 0; i < 2; i++){
console.log("checking: " + nums);
// Applies the function `(num) => num !== 0` to each element of `nums`.
// If the result is true for every element, returns true.
// Otherwise, returns false.
const noZerosFound = nums.every( (num) => num !== 0);
console.log("noZerosFound: " + noZerosFound);
console.log("\n");
}
See the .every method and arrow functions on MDN for further explanation.
There are already good answers here. Let me introduce this way as an extra answer.
const test = [2, 0, 3, 4, 5, 6, 7];
console.log(!test.includes(0));
const test2 = [2, 1, 3, 4, 5, 6, 7];
console.log(!test2.includes(0));
.includes()
array.includes(<value>)
.includes() returns true if a given value is in an array, false if not.
!test.includes(0) returns true if 0 is NOT in test. false if 0 IS in test.
I'm working on finding the mode for a given array. The way I've gone about it so far is to reduce the array into object keys, and set each of the key values to zero. Now I want to scan the array again and increment the value by 1 for each occurrence of the element in the array.
I have what I think should work, but the key with multiple occurrences isn't getting incremented. All values just read as 1.
My code so far:
const mode = function(arr) {
const reducer = arr.reduce((accumulator, currentValue) => (accumulator[currentValue] = 0, accumulator), {});
for (let key in reducer) {
for (let i = 0; i < arr.length; i++) {
if (reducer[key] === arr[i]) {
reducer[key]++;
}
}
}
return reducer;
};
console.log(mode([6,2,3,4,9,6,1,0,5]));
Which returns:
{ '0': 1, '1': 1, '2': 1, '3': 1, '4': 1, '5': 1, '6': 1, '9': 1 }
What am I missing to change '6': 1 to '6': 2 ?
Any guidance is appreciated. Still getting the hang of things, open to any suggestions or feedback. Thank you!
The error in your code (as noted by #Pointy) is the comparison reducer[key] === arr[i] that should be if (key === arr[i]) {. Since you are using strict equality (===) you'll need to cast the key to a number, or use the equality (==) operator instead.
const mode = function(arr) {
const reducer = arr.reduce((accumulator, currentValue) => (accumulator[currentValue] = 0, accumulator), {});
for (let key in reducer) {
for (let i = 0; i < arr.length; i++) {
if (+key === arr[i]) {
reducer[key]++;
}
}
}
return reducer;
};
console.log(mode([6, 2, 3, 4, 9, 6, 1, 0, 5]));
However, you are doing some redundant work, since you can compute the number of occurrences when you reduce the array to an object:
const mode = function(arr) {
return arr.reduce((accumulator, currentValue) => {
accumulator[currentValue] = (accumulator[currentValue] ?? 0) + 1;
return accumulator;
} , {});
};
console.log(mode([6,2,3,4,9,6,1,0,5]));
I am trying to split an array which has a repeating pattern of elements 1, 2, 3, and 4. I want to turn my array [1,2,3,4,5,6,7,8,9,10] into four arrays: [1,5,10], [2,6,11], [3,7,12], and [4,8,13]. I tried using multiples, but the result creates the new arrays in a wrong order. Here is my attempt:
var upload_names_and_ids = [
"Certificat de salaire", //first line is the upload's visible title
"certificat-de-salaire", //second line is the upload's id
"no-info-circle", //third line is the info-circle class
"", //fourth line is the info-circle text
"Allocations Familiales",
"alloc-familiales",
"no-info-circle",
"",
"Courrier Impot (déclaration précédente)",
"courrier-impot",
"info-circle right",
""
];
//Seperate our first array into 4
var upload_names = [];
var upload_ids = [];
var upload_info_circle_class = [];
var upload_info_circle_content = [];
for (var i=0; i<upload_names_and_ids.length; i++){
if (i%4==0) {
upload_info_circle_content.push(upload_names_and_ids[i]);
} else if (i%3==0) {
upload_info_circle_class.push(upload_names_and_ids[i]);
} else if (i%2==0) {
upload_names.push(upload_names_and_ids[i]);
} else {
upload_ids.push(upload_names_and_ids[i]);
}
}
Any help is much appreciated, thank you!
You could take a remainder with index and wanted length.
const
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
length = 4,
result = array.reduce(
(r, v, i) => (r[i % length].push(v), r),
Array.from({ length }, _ => [])
);
console.log(result);
If you like to use predeclared array directly, you could replace this line
Array.from({ length }, _ => [])
with
[upload_names, upload_ids, upload_info_circle_class, upload_info_circle_content]
where the accumulator of Array#reduce keeps the object references.
It's not i%3==0 (which matches 0, 3, 6, …) but i%4==1 (to match 1, 5, 10, …). Same for i%2==0.
I would add a helper sliceN that takes an array and a positive integer. Then returns an array of arrays where the inner arrays are of length n.
sliceN([1,2,3,4,5,6,7,8,9], 3) //=> [[1,2,3], [4,5,6], [7,8,9]]
sliceN([1,2,3,4,5,6], 2) //=> [[1,2], [3,4], [5,6]]
Then also add a helper transpose that transposes a matrix.
transpose([[1,2,3], [4,5,6], [7,8,9]]) //=> [[1,4,7], [2,5,8], [3,6,9]]
transpose([[1,2], [3,4], [5,6]]) //=> [[1,3,5], [2,4,6]]
With these two helpers you can create the wanted result with ease.
const upload_names_and_ids = [
"Certificat de salaire", //first line is the upload's visible title
"certificat-de-salaire", //second line is the upload's id
"no-info-circle", //third line is the info-circle class
"", //fourth line is the info-circle text
"Allocations Familiales",
"alloc-familiales",
"no-info-circle",
"",
"Courrier Impot (déclaration précédente)",
"courrier-impot",
"info-circle right",
""
];
const [
upload_names,
upload_ids,
upload_info_circle_class,
upload_info_circle_content,
] = transpose(sliceN(upload_names_and_ids, 4));
console.log(upload_names);
console.log(upload_ids);
console.log(upload_info_circle_class);
console.log(upload_info_circle_content);
function sliceN(array, n) {
const slices = [];
for (let i = 0; i < array.length; i += n) {
slices.push(array.slice(i, i + n));
}
return slices;
}
function transpose(rows) {
if (rows.length == 0) return [];
const columns = rows[0].map(cell => Array.of(cell));
for (let iRow = 1; iRow < rows.length; iRow += 1) {
for (let iCol = 0; iCol < columns.length; iCol += 1) {
columns[iCol].push(rows[iRow][iCol]);
}
}
return columns;
}
If you are already use a library with helper functions chances are that one or both of these data transforming methods are present. sliceN can often be found as something with split, slice or chunk in the name. transpose is very specific and if present will probably be present under the same name.
As an example Ramda offers both these methods.
R.transpose(R.splitEvery(4, upload_names_and_ids))