Related
I have an array containing numbers, in that array there're some numbers that occur many times in consecutive order one after the other, and I want to compress those repeated numbers into a very specific format 'Number*Times' to reduce the size of the array:
input: [0, 1, 2, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 5, 6, 0]
---------^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^--------
output: [0, 1, 2,'0x3', 3, 2, '0x6', 5, 6, 0]
let array = [0, 1, 2, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 5, 6, 0];
let string = array.toString();
let string_compressed = string.replace(/(\d+,)(\1)+/g, (x) => {
return "Number*" + x.split(",").length + ",";
});
let array_compressed = string_compressed
.split(",")
.map((x) => (isNaN(Number(x)) ? x : Number(x)));
console.log(array_compressed); //[0, 1, 2, 'Number*4', 3, 2, 'Number*7', 5, 6, 0]
I don't know how to get the number that repeated so I put Number instead!
I used regex to solve it, I know if you think to solve problem with regex, they become two problems!
BUT Guys I'm sure this isn't the efficient way to solve this problem, And there're other ways to solve it!
what do you suggest if you want to solve this problem?
Because your regex to find how many numbers repeat already only matches numbers that are in consecutive order in your array, you can simply just take the first index of the x.split(",") array and return that.
Edit:
Also, as #qrsngky out, your x.split(",").length wasn't actually the right length, because when you split it by comma, there is a null character at the end:
let array = [0, 1, 2, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 5, 6, 0];
let string = array.toString();
let string_compressed = string.replace(/(\d+,)(\1)+/g, (x) => {
console.log(x.split(","));
return "Number*" + x.split(",").length + ",";
});
let array_compressed = string_compressed
.split(",")
.map((x) => (isNaN(Number(x)) ? x : Number(x)));
console.log(array_compressed);
Sorry for missing that, and props to the comments! I just fixed it by subtracting one from the length.
Edit 2:
For edge cases, we can just add a comma and use slice.
I attached the complete fixed code snippet below:
let array = [0, 1, 2, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 5, 6, 0, 0, 0];
let string = array.toString() + ",";
let string_compressed = string.replace(/(\d+,)(\1)+/g, (x) => {
return x.split(",")[0] + "*" + (x.split(",").length - 1) + ",";
});
let array_compressed = string_compressed
.slice(0, -1)
.split(",")
.map((x) => (isNaN(Number(x)) ? x : Number(x)));
console.log(array_compressed);
Assume your original array consists of none other than numbers.
Non-regex approach: based on a for loop and counting how many repetitions had been encountered.
let array = [0, 1, 2, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 5, 6, 0]
let buffer = [];
let currentNum = array[0], count = 1;
for (let i = 1; i < array.length; i++) {
if (array[i] === currentNum) {
++count;
} else {
buffer.push( count === 1 ? currentNum : (currentNum + 'x' + count) );
currentNum = array[i];
count = 1;
}
}
//don't forget the last number
if(currentNum !== undefined) buffer.push( count === 1 ? currentNum : (currentNum + 'x' + count) );
console.log(buffer);
The if(currentNum !== undefined) check is only useful in case it's an empty array.
Another example of how not to do it with string manipulation by coding what you want done:
function packArray(array) {
var packed = [];
for( var i = 0; i < array.length; i=j) {
var entry = array[i];
for(var j = i+1; array[j] === entry && j<array.length; ++j);
packed.push( j > i+1 ? `${entry}x${j-i}` : entry);
}
return packed;
}
console.log( packArray([0, 1, 2, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 5, 6, 0]))
You could substitute let for var except for var j which should remain the same to allow access to j outside the nested for loop.
I'm trying to create a random board for my project but it finishes without filling the whole board(leaves 0)
I converted the original code from this site:
www.101computing.net/sudoku-generator-algorithm/
from python to javascript manually and checked all the functions that I created but some things were wrong.
would love to get some help here thnks!
the code:
let grid = Array(9).fill().map(()=>Array(9).fill(0))
let numberList = [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(grid);
fillGrid(grid)
console.log(grid)
function fillGrid(grid){
//var counter;
// Find next empty cell
for (i in range(0,81)){
row = ~~(i / 9);
col = i % 9;
if (grid[row][col]== 0){
shuffle(numberList);
for (g in numberList){
value = numberList[g]
// Check that this value has not already be used on this row and col
if (!checkForNumebrInRaw(grid,row,value) && !checkForNumebrInColomn(grid,col,value)){
// Identify which of the 9 squares we are working on
square = []
if (row<3){
if (col<3){
square = getSquare(grid,0,3,0,3);
}else if (col<6){
square = getSquare(grid,3,6,0,3);
}else{
square = getSquare(grid,6,9,0,3);
}
}
else if (row<6){
if (col<3){
square = getSquare(grid,0,3,3,6);
}else if (col<6){
square = getSquare(grid,3,6,3,6);
}else{
square = getSquare(grid,6,9,3,6);
}
}
else{
if (col<3){
square = getSquare(grid,0,3,6,9);
}else if (col<6){
square = getSquare(grid,3,6,6,9);
}else{
square = getSquare(grid,6,9,6,9);
}
}
// Check that this value has not already be used on this 3x3 square
if (!checkForNumInSquare(square,value)){
grid[row][col] = value;
if (checkGrid(grid)){
return true;
}else
{
if (fillGrid(grid)){
return true;
}
}
}
}
break
}
grid[row][col] = 0;
}
}
}
function range(start, end) {
let res=[];
for (i=start;i<end;i++){
res.push(i)
}
return res
};
function getSquare(mat,a,b,c,d) {
var _pj_a = []
_pj_b = range(c, d);
for (var _pj_c = 0, _pj_d = _pj_b.length; _pj_c < _pj_d; _pj_c += 1) {
var i = _pj_b[_pj_c];
_pj_a.push(mat[i].slice(a, b));
}
return _pj_a;
};
function checkForNumebrInRaw(grid,raw,num){
for (let i = 0; i<grid.length;i++){
if (grid[raw][i] == num){return true;}
}
return false;
}
function checkForNumebrInColomn(grid,colomn,num){
for (let i = 0; i<grid.length;i++){
if (grid[i][colomn] == num){return true;}
}
return false;
}
function shuffle(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
function checkForNumInSquare(grid,num){
for (let i=0;i<grid.length;i++){
for(let j=0;j<grid[i].length;j++){
if (grid[i][j]== num){return true;}
}
}
return false
}
// A function to check if the grid is full
function checkGrid(grid){
for (let i=0;i<grid.length;i++){
for(let j=0;j<grid[i].length;j++){
if (grid[i][j]== 0){return false;}
}
}
return true
}
output:
[
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
]
]
[
[
3, 8, 7, 4, 1,
2, 5, 6, 9
],
[
5, 9, 6, 3, 7,
8, 1, 4, 0
],
[
1, 2, 4, 5, 6,
9, 7, 3, 8
],
[
9, 4, 3, 1, 5,
7, 0, 8, 2
],
[
2, 1, 8, 0, 9,
4, 3, 7, 6
],
[
7, 0, 5, 6, 8,
3, 9, 1, 4
],
[
4, 7, 2, 8, 0,
1, 6, 9, 5
],
[
0, 6, 9, 2, 3,
5, 8, 0, 7
],
[
8, 3, 1, 7, 0,
6, 4, 2, 0
]
]
Ok so after a million tries i made it!
// true - row and colomn without the number
function rowAndColomnCheck(grid,row,col,num){
function checkForNumebrInRaw(grid,row,num){
for (let i = 0; i<grid.length;i++){
if (grid[row][i] == num){return true;}
}
return false;
}
function checkForNumebrInColomn(grid,colomn,num){
for (let i = 0; i<grid.length;i++){
if (grid[i][colomn] == num){return true;}
}
return false;
}
if (!checkForNumebrInColomn(grid,col,num) && !checkForNumebrInRaw(grid,row,num)){
return true;
}else{
return false;
}
};
function range(start, end) {
let res=[];
for (i=start;i<end;i++){
res.push(i)
}
return res
};
function getSquare(mat,a,b,c,d) {
var _pj_a = []
_pj_b = range(c, d);
for (var _pj_c = 0, _pj_d = _pj_b.length; _pj_c < _pj_d; _pj_c += 1) {
var i = _pj_b[_pj_c];
_pj_a.push(mat[i].slice(a, b));
}
return _pj_a;
};
function shuffle(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
};
// check if number is in sqare given
function checkForNumInSquare(grid,num){
for (let i=0;i<grid.length;i++){
for(let j=0;j<grid[i].length;j++){
if (grid[i][j]== num){return true;}
}
}
return false
};
// A function to check if the grid is full
function checkGrid(grid){
for (let i=0;i<grid.length;i++){
for(let j=0;j<grid[i].length;j++){
if (grid[i][j]== 0){return false;}
}
}
// complete
return true
};
function fillSudoku(mat){
for(let i in range(0,81)){
var mainRow = ~~(i / 9);
var mainCol = i % 9;
if (mat[mainRow][mainCol] == 0){
shuffle(numberList);
for (let value of numberList){
if(rowAndColomnCheck(mat,mainRow,mainCol,value)){
var mySquare = [[]];
if(mainRow<3){
if (mainCol<3){
mySquare = getSquare(mat,0,3,0,3);
}
else if (mainCol<6){
mySquare = getSquare(mat,3,6,0,3);
}
else{
mySquare = getSquare(mat,6,9,0,3);
}
}
else if(mainRow<6){
if (mainCol<3){
mySquare = getSquare(mat,0,3,3,6);
}
else if (mainCol<6){
mySquare = getSquare(mat,3,6,3,6);
}
else{
mySquare = getSquare(mat,6,9,3,6);
}
}
else{
if (mainCol<3){
mySquare = getSquare(mat,0,3,6,9);
}
else if (mainCol<6){
mySquare = getSquare(mat,3,6,6,9);
}
else{
mySquare = getSquare(mat,6,9,6,9);
}
}
bol_t = checkForNumInSquare(mySquare,value);
if (bol_t == false){
mat[mainRow][mainCol] = value;
if (checkGrid(mat)){
return true;
}
else{
if (fillSudoku(mat)){
return true;
}
}
}
}
}
break
}
}
mat[mainRow][mainCol] = 0;
};
var numberList = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var grid = Array(9).fill().map(()=>Array(9).fill(0));
fillSudoku(grid);
console.log(grid);
I want to compare a dicitonary, which has certain preferences of a coachee, with other dictionaries, which contain the profil of coaches.
So every Coach got a score on how well he matches the coachee preference, or gets excluded with a score of -1 because he doesnt match an important preference.
One coachee will be compared to 24 coaches, and get a score, so i can see which is the best match.
QUESTION: How can I loop this?
Here is a code example:
//coachee\\
var coachee = {
"geschlecht": 1,
"alter_option_1": 1,
"alter_option_2": 1,
"alter_option_3": 0,
"themen_option_1": 1,
"themen_option_2": 0,
"themen_option_3": 0,
"branche_option_1": 1,
"branche_option_2": 0,
"branche_option_3": 0,
"erfahrung_option_1": 1,
"erfahrung_option_2": 0,
"erfahrung_option_3": 1,
"sprache_option_1": 1,
"sprache_option_2": 0,
"sprache_option_3": 0,
}
//coach1\\
var coach1 = {
coach1_answers_geschlecht : 2,
coach1_answers_alter_option_1 : 0,
coach1_answers_alter_option_2 : 1,
coach1_answers_alter_option_3 : 0,
coach1_answers_themen_option_1 : 1,
coach1_answers_themen_option_2 : 0,
coach1_answers_themen_option_3 : 1,
coach1_answers_branche_option1 : 1,
coach1_answers_branche_option2 : 1,
coach1_answers_branche_option3 : 0,
coach1_answers_erfahrung_option1 : 1,
coach1_answers_erfahrung_option2 : 1,
coach1_answers_erfahrung_option3 : 0,
coach1_answers_sprache_option_1 : 1,
coach1_answers_sprache_option_2 : 1,
coach1_answers_sprache_option_3 : 1,
};
///COMPARISON\\\
//Themen\\
if (answers["themen_option_1"] == 1 && coach1_answers_themen_option_1 == 1) {
coach1_themen1_score = 1;
} else {
coach1_themen1_score = 0
}
if (answers["themen_option_2"] == 1 && coach1_answers_themen_option_2 == 1) {
coach1_themen2_score = 1;
} else {
coach1_themen2_score = 0
}
if (answers["themen_option_3"] == 1 && coach1_answers_themen_option_3 == 1) {
coach1_themen3_score = 1;
} else {
coach1_themen3_score = 0
}
var coach1_themen_score = coach1_themen1_score + coach1_themen2_score + coach1_themen3_score
//Branche\\
if (answers["branche_option_1"] == 1 && coach1_answers_branche_option1 == 1) {
coach1_branche1_score = 1;
} else {
coach1_branche1_score = 0
}
if (answers["branche_option_2"] == 1 && coach1_answers_branche_option2 == 1) {
coach1_branche2_score = 1;
} else {
coach1_branche2_score = 0
}
if (answers["branche_option_3"] == 1 && coach1_answers_branche_option3 == 1) {
coach1_branche3_score = 1;
} else {
coach1_branche3_score = 0
}
var coach1_branche_score = coach1_branche1_score + coach1_branche2_score + coach1_branche3_score
//Erfahrung\\
if (answers["erfahrung_option_1"] == 1 && coach1_answers_erfahrung_option1 == 1) {
coach1_erfahrung1_score = 1;
} else {
coach1_erfahrung1_score = 0
}
if (answers["erfahrung_option_2"] == 1 && coach1_answers_erfahrung_option2 == 1) {
coach1_erfahrung2_score = 1;
} else {
coach1_erfahrung2_score = 0
}if (answers["erfahrung_option_3"] == 1 && coach1_answers_erfahrung_option3 == 1) {
coach1_erfahrung3_score = 1;
} else {
coach1_erfahrung3_score = 0
}
var coach1_erfahrung_score = coach1_erfahrung1_score + coach1_erfahrung2_score + coach1_erfahrung3_score
//Score\\
var coach1_score = (coach1_alter_score + coach1_themen_score + coach1_branche_score + coach1_erfahrung_score)*10
///EXCLUSION\\\
//Alter\\
if (answers["alter_option_1"] == 1 && coach1_answers_alter_option_1 == 1) {
coach1_alter_score = 1;
} else if (answers["alter_option_2"] == 1 && coach1_answers_alter_option_2 == 1) {
coach1_alter_score = 1;
} else if (answers["alter_option_3"] == 1 && coach1_answers_alter_option_3 == 1) {
coach1_alter_score = 1;
} else {
coach1_score = -1
}
//Sprache\\
if (answers["sprache_option_1"] == 1 && coach1_answers_sprache_option_1 == 1 ) {
coach1_sprache_score = 1;
} else if (answers["sprache_option_2"] == 1 && coach1_answers_sprache_option_2 == 1 ) {
coach1_sprache_score = 1;
} else if (answers["sprache_option_3"] == 1 ) {
coach1_sprache_score = 1;
} else {
coach1_score = -1;
}
//Geschlecht\\
if (answers["geschlecht"] == 3) {
coach1_geschlecht_score = 1;
} else if (answers["geschlecht"] == coach1_answers_geschlecht) {
coach1_geschlecht_score = 1;
} else {
coach1_score = -1;
}
//Coach2\\
var coach2 = {
coach2_answers_geschlecht : 2,
coach2_answers_alter_option_1 : 0,
coach2_answers_alter_option_2 : 1,
coach2_answers_alter_option_3 : 0,
coach2_answers_themen_option_1 : 1,
coach2_answers_themen_option_2 : 1,
coach2_answers_themen_option_3 : 1,
coach2_answers_branche_option1 : 1,
coach2_answers_branche_option2 : 1,
coach2_answers_branche_option3 : 0,
coach2_answers_erfahrung_option1 : 1,
coach2_answers_erfahrung_option2 : 1,
coach2_answers_erfahrung_option3 : 0,
coach2_answers_sprache_option_1 : 1,
coach2_answers_sprache_option_2 : 1,
coach2_answers_sprache_option_3 : 1,
};
As a result I want an Array with all the scores like:
coaches_score = [coach1_score, coach2_score, ...]
Manually i would repeat the //COMPARISON\ and //EXCLUSION\ Block for every Coach, but i would have to do this 24 times. Is there any way to Loop this?
Thanks a lot guys.
I suggest to change the data structure to a more iterable style with arrays and take same keys for calculating score with a group of keys.
const
getScore = coach => {
const
score = {},
keys1 = ['themen', 'branche', 'erfahrung'],
keys2 = ['alter', 'sprache'];
keys1.forEach(k => score[k] = coachee[k].reduce((s, v, i) => s + v * coach[k][i], 0));
score.score = keys1.reduce((s, k) => s + score[k], 0) * 10;
keys2.forEach(k => {
score[k] = +coachee[k].slice(0, -1).some((v, i) => v * coach[k][i]) || +coach1[k][coach[k].length - 1] || 0;
if (!score[k]) score.score = -1;
});
score.geschlecht = +(coach.geschlecht === 3 || coachee.geschlecht === coach.geschlecht)
if (!score.geschlecht) score.score = -1;
return score;
},
coachee = {
geschlecht: 1,
alter: [1, 1, 0, 0],
themen: [1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
branche: [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0],
erfahrung: [1, 0, 1, 0, 0],
sprache: [1, 0, 0]
},
coach1 = {
geschlecht: 2,
alter: [0, 1, 0, 1],
themen: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1],
branche: [1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1],
erfahrung: [1, 1, 0, 0, 1],
sprache: [1, 1, 1]
};
console.log(getScore(coach1));
Ok, i still dont get the code, because it is way to complexe for my understanding of Java Script, but i still got it working for me. I edited this to the Code:
var coach1_values = getScore(coach1)
var coach2_values = getScore(coach2)
var coach3_values = getScore(coach3);
//Summieren der Werte zum Score\\
const sumValues = obj => Object.values(obj).reduce((a, b) => a + b);
if (coach1_values.score != -1) {
var coach1_score = sumValues(coach1_values);
} else coach1_score = -1;
if (coach2_values.score != -1) {
var coach2_score = sumValues(coach2_values);
} else coach2_score = -1;
if (coach3_values.score != -1) {
var coach3_score = sumValues(coach3_values);
} else coach3_score = -1;
I dont get why the score gets the value 110 if it matches the "geschlecht", but its no problem, because everyone gets the 110 to their score. Thanks a lot again
I need to find the maximum slice of the array which contains no more than two different numbers.
Here is my array [1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8]
My thought process on this is to find the numbers that are not repeated and return their index within a new array.
Here is what I have so far:
function goThroughInteger(number) {
var array = [];
//iterate the array and check if number is not repeated
number.filter(function (element, index, number) {
if(element != number[index-1] && element != number[index+1]) {
array.push(index);
return element;
}
})
console.log(array);
}
goThroughInteger([1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8]);
I'm unsure where to go next, I'm struggling to understand the question that being - find the maximum slice which contains no more than two different numbers - that confuses me.
A solution with a single loop, which checks the last values and increments a counter.
function getLongestSlice(array) {
var count = 0,
max = 0,
temp = [];
array.forEach(function (a) {
var last = temp[temp.length - 1];
if (temp.length < 2 || temp[0].value === a || temp[1].value === a) {
++count;
} else {
count = last.count + 1;
}
if (last && last.value === a) {
last.count++;
} else {
temp.push({ value: a, count: 1 });
temp = temp.slice(-2);
}
if (count > max) {
max = count;
}
});
return max;
}
console.log(getLongestSlice([58, 800, 0, 0, 0, 356, 8988, 1, 1])); // 4
console.log(getLongestSlice([58, 800, 0, 0, 0, 356, 356, 8988, 1, 1])); // 5
console.log(getLongestSlice([1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8])); // 10
function goThroughInteger(array) {
var solutionArray = [];
var max = 0;
for (var i = 0; i <= array.length; i++) {
for (var j = i + 1; j <= array.length; j++) {
var currentSlice= array.slice(i,j);
var uniqSet = [...new Set(currentSlice)];
if(uniqSet.length <3) {
if(currentSlice.length>max) {
max= currentSlice.length;
}
}
}
}
console.log(max);
}
goThroughInteger([1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8]);
This solution checks every possible slice of the array, checks if it has not more than 2 different numbers and finally prints out the length of the longest slice.
This is a possible solution, with complexity O(n²) (as pointed out by #le_m in the comments)
goThroughInteger = (list) => {
let scores = list.reduce((slices, num, pos) => {
let valid = [num];
let count = 0;
for (let i = pos; i < list.length; i++) {
if (valid.indexOf(list[i]) == -1) {
if (valid.length < 2) {
valid.push(list[i]);
count++;
} else {
break;
}
} else {
count++;
}
}
slices[pos] = { pos, count };
return slices;
}, []);
scores.sort((a, b) => b.count - a.count);
let max = scores[0];
return list.slice(max.pos, max.pos + max.count);
};
console.log(goThroughInteger([1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8]));
console.log(goThroughInteger([58, 800, 0, 0, 0, 356, 8988, 1, 1]));
```
The solution calculates the 'score' at every position of the input list, counting the length of a sequence of no more than 2 different values, then takes the result with the highest score and extracts a slice from the original list based on that information.
It can definitely be cleaned and optimized but I think it's a good starting point.
Using the sliding window algorithm in O(n) time:
const arr = [1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8, 1, 1 ,1 ,1, 8, 1, 1, 8, 8];
const map = {
length: 0
};
let required = [];
for(start = 0, end = 0; end <= arr.length; ){
if(map.length > 2){
if(map[arr[start]] === 1){
delete map[arr[start]];
map.length --;
}else{
map[arr[start]]--;
};
start++;
}else{
if(end - start > required.length){
required = arr.slice(start, end);
};
if(map[arr[end]]){
map[arr[end]]++;
}else{
map[arr[end]] = 1;
map.length++;
}
end++;
}
}
console.log(required);
Given this array:
[1, 1, 2, 1, 1, 1, 2, 3, 4, 4, 4, 6, 4, 4]
How can I efficently count the nearest same elements in array, the result I would expect is:
1 => 2,
2 => 1,
1 => 3,
2 => 1,
3 => 1,
4 => 3,
6 => 1,
4 => 2
I don't know how to formulate correctly the question but I think the example is pretty clear.
I tried using reduce to make more compact and elegant but I always get a value with total number of same value in array.
let result = testArray.reduce((allValues, value) => {
if(value in allValues){
allValues[value]++;
} else {
allValues[value] = 1;
}
return allValues;
}, {});
You could check the last element and if equal, increment count, if not push a new object to the result set.
var array = [1, 1, 2, 1, 1, 1, 2, 3, 4, 4, 4, 6, 4, 4],
count = array.reduce((r, a, i, aa) => {
if (aa[i - 1] === a) {
r[r.length - 1].count++;
} else {
r.push({ value: a, count: 1 });
}
return r;
}, []);
console.log(count);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Another solution using Array.prototype.reduce and a hash table - see demo below:
var array = [1, 1, 2, 1, 1, 1, 2, 3, 4, 4, 4, 6, 4, 4];
var result = array.reduce(function(hash){
return function(p,c,i){
hash[c] = (hash[c] || 0) + 1;
if(hash.prev && (hash.prev !== c || i == array.length - 1)) {
let obj= {};
obj[hash.prev] = hash[hash.prev];
delete hash[hash.prev];
p.push(obj);
}
hash.prev = c;
return p;
}
}(Object.create(null)),[]);
console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}
While Array.prototype.reduce is a nice function, it does have some compatibility issues.
Here is a solution using old school for loops:
var arr = [1, 1, 2, 1, 1, 1, 2, 3, 4, 4, 4, 6, 4, 4];
var results = [];
for (var indexA = 0; indexA < arr.length; indexA++) {
var a = arr[indexA];
if (results.length > 0) {
if (a == results[results.length - 1]["value"]) {
continue;
}
}
var r = { value: a, index: indexA, count: 0 };
for (var indexB = indexA; indexB < arr.length; indexB++) {
var b = arr[indexB];
if (a != b) {
break;
}
r.count++;
}
results.push(r);
}
console.log(results);
The posted solutions are fine but as noted by #Emil S. Jørgensen there might be compatibility issues using Array.reduce. Also, the suggested old school solution by #Emil S. Jørgensen uses two loops. If you want to have a slightly more efficient,simple and straightforward solution which will work in all browsers then use:
var arr = [1, 1, 2, 1, 1, 1, 2, 3, 4, 4, 4, 6, 4, 4];
var result = [];
var current = arr[0];
var count = 1;
for (var i = 1; i <= arr.length; i++)
{
if(arr[i] === current)
{
count+= 1;
}
else
{
var newObj = {};
newObj[current] = count;
result.push(newObj);
current = arr[i];
count = 1;
}
}
console.log(result); //prints the solution