I've written this code. It seems to run correctly through the first set of nested for loops. When I put in debugger above the final for loop, it will return the correct thing for me (and if I want to return newArray, it will return). What am I doing wrong?
I want it to loop through the letterSplit array I've made of the input, then loop through the values array and find the corresponding value, and push that corresponding value into the newArray. This works so far with 1 letter.
BUT I also want it to work for multiple letters, so that if someone puts in "cat", it will add them all up into a new array "total". That is what I was trying to do with the last for loop. Suggestions? Ideas? Do you see a misplaced word or character somewhere?
var scrabble = function (letter) {
var newLetter = letter.toLowerCase();
var letterSplit = newLetter.split(" ");
var newArray = [];
var stupidArray = [];
var total = 0;
var values = [["a", 1], ["b", 3], ["c", 3], ["d", 2], ["e", 1], ["f", 4], ["g", 2], ["h", 4], ["i", 1], ["j", 8], ["k", 5], ["l", 1], ["m", 3], ["n", 1], ["o", 1],
["p", 3], ["q", 10], ["r", 1], ["s", 1], ["t", 1], ["u", 1], ["v", 4], ["w", 4], ["x", 8], ["y", 4], ["z", 10]];
for (var i=0; i < letterSplit.length; i++) {
for (var i=0; i < values.length; i++) {
if (values[i][0] === letterSplit[0]) {
newArray.push(values[i][1]);
stupidArray += letterSplit.splice(0,1);
}
}
}
for (var i=0; i < newArray.length; i++) {
total += i;
}
var result = total.toString();
return total;
};
Using an Object as a lookup for the letter value would probably be simpler/more sensible. Something like this.
Javascript
var values = {
a: 1,
b: 3,
c: 3,
d: 2,
e: 1,
f: 4,
g: 2,
h: 4,
i: 1,
j: 8,
k: 5,
l: 1,
m: 3,
n: 1,
o: 1,
p: 3,
q: 10,
r: 1,
s: 1,
t: 1,
u: 1,
v: 4,
w: 4,
x: 8,
y: 4,
z: 10
};
function scrabble(word) {
return word.toLowerCase().split('').reduce(function (acc, letter) {
if (values.hasOwnProperty(letter)) {
acc += values[letter];
}
return acc;
}, 0);
}
console.log(scrabble('cat'));
Output
5
On jsFiddle
Your code corrected
Javascript
var scrabble = function (letter) {
var letterSplit = letter.toLowerCase().split(''),
total = 0,
values = [
['a', 1],
['b', 3],
['c', 3],
['d', 2],
['e', 1],
['f', 4],
['g', 2],
['h', 4],
['i', 1],
['j', 8],
['k', 5],
['l', 1],
['m', 3],
['n', 1],
['o', 1],
['p', 3],
['q', 10],
['r', 1],
['s', 1],
['t', 1],
['u', 1],
['v', 4],
['w', 4],
['x', 8],
['y', 4],
['z', 10]
],
i,
j;
for (i = 0; i < letterSplit.length; i++) {
for (j = 0; j < values.length; j++) {
if (values[j][0] === letterSplit[i]) {
total += values[j][1];
break;
}
}
}
return total;
};
console.log(scrabble('cat'));
On jsFiddle
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have multiple arrays in a main/parent array like this:
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
[2, 12],
[2, 12]
];
I have the code to select the arrays that are repeated 3 or more times (> 3) and assign it to a variable.
The code is:
var arr = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]]
arr.sort((a, b) => a[0] - b[0] || a[1] - b[1])
// define equal for array
const equal = (arr1, arr2) => arr1.every((n, j) => n === arr2[j])
let GROUP_SIZE = 3
first = 0, last = 1, res = []
while(last < arr.length){
if (equal(arr[first], arr[last])) last++
else {
if (last - first >= GROUP_SIZE) res.push(arr[first])
first = last
}
}
if (last - first >= GROUP_SIZE) res.push(arr[first])
console.log(res)
So the final result is:
console.log(repeatedArrays);
>>> [[1, 17], [2, 12]]
My problem: But the problem is, I have an array like this {from: [12, 0], to: [14, 30]}.
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
{from: [12, 0], to: [14, 5]},
{from: [12, 0], to: [14, 5]},
{from: [4, 30], to: [8, 20]},
{from: [12, 0], to: [14, 5]},
{from: [4, 30], to: [8, 20]},
[2, 12],
[2, 12]
];
When I try to use the above code, it doesn't work. The error message is:
Uncaught TypeError: arr1.every is not a function
The final result should be:
console.log(repeatedArrays);
>>> [[1, 17], [2, 12], {from: [12, 0], to: [14, 5]}]
How can I make that code above work?
If you introduce a non array into the mix, you need to handle it differently.
Yours already work with array so I'm adding object style check for both sort and equal.
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
{ from: [4, 30], to: [8, 21] },
{ from: [12, 0], to: [14, 5] },
{ from: [12, 0], to: [14, 5] },
{ from: [4, 30], to: [8, 20] },
{ from: [12, 0], to: [14, 5] },
{ from: [4, 30], to: [8, 20] },
[2, 12],
[2, 12]
];
arr.sort((a, b) => {
if (a instanceof Array && b instanceof Array) {
return a[0] - b[0] || a[1] - b[1]
} else if (a instanceof Array || b instanceof Array) {
return a instanceof Array ? -1 : 1
} else {
return a.from[0] - b.from[0] || a.from[1] - b.from[1] || a.to[0] - b.to[0] || a.to[1] - b.to[1]
}
});
// define equal for array
const equal = (arr1, arr2) => {
if (arr1 instanceof Array) {
return arr1.every((n, j) => n === arr2[j]);
} else {
if (arr2 instanceof Array) return false;
for (let k in arr1) {
if (!arr1[k].every((n, j) => n === arr2[k][j])) {
return false
}
}
return true;
}
};
let GROUP_SIZE = 3;
(first = 0), (last = 1), (res = []);
while (last < arr.length) {
if (equal(arr[first], arr[last])) last++;
else {
if (last - first >= GROUP_SIZE) res.push(arr[first]);
first = last;
}
}
if (last - first >= GROUP_SIZE) res.push(arr[first]);
console.log(res);
You can use the function reduce for grouping and counting the objects and then execute the function filter for getting the object with count >= 3.
var array = [ [1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12], [2, 12] ];
let result = Object.values(array.reduce((a, [c, b]) => {
let key = `${c}|${b}`;
(a[key] || (a[key] = {count: 0, value: [c, b]})).count++;
return a;
}, {})).filter(o => {
if (o.count >= 3) {
delete o.count;
return true;
}
return false;
}).map(({value}) => value);
console.log(result);
.as-console-wrapper { min-height: 100%; }
Really simple - filter it all, then remove duplicates with Set and JSON methods (because it's nested arrays not objects):
var array = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
[2, 12],
[2, 12]
];
var repeatedArrays = [...new Set(array.filter(e => array.filter(f => JSON.stringify(e.sort()) == JSON.stringify(f.sort()))).map(JSON.stringify))].map(JSON.parse);
console.log(repeatedArrays);
I try to loop the 2d arrays, but the I variable is undefined or not iterable, why?
can anyone tell me ??
function sum (arr) {
var total = 0
for(let [a1,a2,a3] of arr){
for(let i of [a1,a2,a3]){
for(let j of i){
total += j
}
}
if(typeof a2 == "undefined" && typeof a3 == "undefined"){
a2 = [0]
a3 = [0]
}
}
};
console.log(sum([
[
[10, 10],
[15],
[1, 1]
],
[
[2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[4],
[9, 11]
],
[
[3, 5, 1],
[1, 5, 3],
[1]
],
[
[90]
]
]));
but when i sum another 2D array, it works, like this :
function sum (arr) {
var total = 0
for(let [a1,a2,a3] of arr){
for(let i of [a1,a2,a3]){
for(let j of i){
total += j
}
}
}
return total
}
console.log(sum([
[
[4, 5, 6],
[9, 1, 2, 10],
[9, 4, 3]
],
[
[4, 14, 31],
[9, 10, 18, 12, 20],
[1, 4, 90]
],
[
[2, 5, 10],
[3, 4, 5],
[2, 4, 5, 10]
]
]));
i try to loop 3 times for this 2d arrays, the first top code is each lengths are diffreen in array
and the last code is same,
Cause
let [a1,a2,a3] of [ [90] ])
will result in a2 and a3 being undefined, therefore in the following line it is:
for(const i of [90, undefined, undefined])
And at the second index it does:
for(let j of undefined)
which doesnt work.
You just need to move your if statement that checks if the value is undefined and assigns it to zero if it is ahead of the part of code that iterates over those values. You were getting this error because there wasn't anything there.
function sumTwo(arr) {
var total = 0
for(let [a1,a2,a3] of arr){
if(typeof a2 == "undefined" && typeof a3 == "undefined"){
a2 = [0]
a3 = [0]
}
for(let i of [a1,a2,a3]){
for(let j of i){
total += j
}
}
}
return total
};
console.log(sumTwo([
[
[10, 10],
[15],
[1, 1]
],
[
[2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[4],
[9, 11]
],
[
[3, 5, 1],
[1, 5, 3],
[1]
],
[
[90]
]
])); //prints 237
When you say
let [a1,a2,a3] of [ [90] ])
there is no a2 or a3 there...
My suggestion would be using the code before you get into the first for loop:
if(arr.length < 3){
for(let y = arr.length, y > 3, y++ ){
arr.push(0)
}
}
Cheers!
It's probably better to recursively reduce the array using concat until you have a flat array and then reduce that to the sum of it's numbers:
const arr = [
[[10, 10], [15], [1, 1]],
[[2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [4], [9, 11]],
[[3, 5, 1], [1, 5, 3], [1]],
[[90]],
];
const flatten = (arr) => {
const recur = (result, item) =>
!Array.isArray(item)
? result.concat(item)
: result.concat(item.reduce(recur, []));
return arr.reduce(recur, []);
};
console.log(
flatten(arr).reduce((result, item) => result + item, 0),
);
This is my array:
[
['x', 1],
['y', 2],
['z', 3],
['F', "_180"],
['x', 1],
['y', 2],
['z', 3],
['t', 4]
['F', "_360"],
['x', 1],
['y', 2],
['z', 3],
['t', 4],
['m', 5]
['F', "_480"],
]
This is what I want to achieve:
[{
profile_180: {
x: 1,
y: 2,
z: 3
}
}, {
profile_360: {
x: 1,
y: 2,
z: 3,
t: 4
}
}, {
profile_480: {
x: 1,
y: 2,
z: 3
t: 4,
m: 5
}
}]
How do I get this?
data = [
['x', 1],
['y', 2],
['z', 3],
['F', "_180"],
['x', 1],
['y', 2],
['z', 3],
['t', 4],
['F', "_360"],
['x', 1],
['y', 2],
['z', 3],
['t', 4],
['m', 5],
['F', "_480"],
];
var result = {};
var current = {};
data.forEach(function(row) {
if (row[0] == 'F') {
result['profile' + row[1]] = current;
current = {};
} else {
current[row[0]] = row[1];
}
});
console.log(result);
<!-- results pane console output; see http://meta.stackexchange.com/a/242491 -->
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
You can do it by,
var res = [], tmp = {}, obj = {};
x.forEach(function(itm,i) {
if(itm[0] !== "F"){
tmp[itm[0]] = itm[1];
} else {
obj["profile_" + itm[1]] = tmp;
res.push(obj);
tmp = {}, obj ={};
}
});
where x is the array that contains the data.
try this
var obj = [
['x', 1],
['y', 2],
['z', 3],
['F', "_180"],
['x', 1],
['y', 2],
['z', 3],
['t', 4],
['F', "_360"],
['x', 1],
['y', 2],
['z', 3],
['t', 4],
['m', 5],
['F', "_480"],
];
var output = [];
var tmpArr = {};
obj.forEach(function(value,index){
console.log(value);
if (value[0] != 'F' )
{
tmpArr[value[0]] = value[1];
}
else
{
var profileValue = "Profile_" + value[1];
var tmpObj = {};
tmpObj[profileValue] = tmpArr;
output.push( tmpObj );
tmpArr = {};
}
});
document.body.innerHTML += JSON.stringify(output,0,4);
I have this javascript array:
[['a', 'x', 1],
['a', 'y', 2],
['b', 'x', 3],
['b', 'z', 4],
['c', 'y', 5],
['c', 'z', 6]]
How do I pivot it to something like below with the 2nd column ('x', 'y', 'z') from above going across.
[['a', 1, 2, null],
['b', 3, null, 4],
['c', null, 5, 6]]
EDIT:
Sorry I was unclear. The answers so far seem to be referencing a static length/value for x, y, z. The array will be dynamic and can have anything in the 2nd column (ex. 't','u','v','w' instead of 'x','y','z'). I think I need to fill the array up first with nulls for all the possible combinations and then push in the values.
Thanks..
Going by Fabricio's comment, here is how you can accomplish something similar:
var result = {};
for(var i=0;i< basearray.length;i++){
if(!result[basearray[i][0]]){
result[basearray[i][0]]={};
}
result[basearray[i][0]][basearray[i][1]]=basearray[i][2];
}
Note that this returns an object or hashmap, not strictly an array, but the data is more organised and it can easily be turned into an array if you so wish. Here is a demonstration (check your console).
By adding this code:
var count=0;
for(var key in result){
result[count]=[];
result[count][0]=key;
result[count][1]=result[key].x||null;
result[count][2]=result[key].y||null;
result[count][3]=result[key].z||null;
count++;
}
your result object now simulates both structures, your original array of arrays, and the suggested key value pairs. You can see the results here: http://jsfiddle.net/9Lakw/3/
Here is what result looks like:
{
"a":{
"x":1,
"y":2
},
"b":{
"x":3,
"z":4
},
"c":{
"y":5,
"z":6
},
"0":[
"a",
1,
2,
null
],
"1":[
"b",
3,
null,
4
],
"2":[
"c",
null,
5,
6
]
}
Here's how I'd do it, with arrays and null fillers as in the question. This assumes that coords for given points always come in succession.
var arr = [['a', 'x', 1],
['a', 'y', 2],
['b', 'x', 3],
['b', 'z', 4],
['c', 'y', 5],
['c', 'z', 6]];
var aux = {
x: 1,
y: 2,
z: 3
},
output = [],
lastItem,
currItem;
for (var i = 0; i < arr.length; i++) {
currItem = arr[i];
if (currItem[0] !== lastItem) {
lastItem = currItem[0];
output.push([lastItem, null, null, null]);
}
output[output.length-1][aux[currItem[1]]] = currItem[2];
}
console.log(output); //[["a", 1, 2, null], ["b", 3, null, 4], ["c", null, 5, 6]]
Fiddle
Are you sure that's the format you want? It seems more sensible to get:
{
a: {x: 1, y: 2},
b: {x: 3, z: 4},
c: {y: 5, z: 6}
}
Which you can get from:
var results = {};
data.forEach(function(el) {
var name = el[0];
var prop = el[1];
var value = el[2];
results[name] = results[name] || {};
results[name][prop] = value;
})
How can I search for an element within a nested array. Following is what the array looks like
arr = [
["choice1", ['a', [2, 4]], ['b', [1, 3, 4]], ['c', [3, 4]]],
["choice2", ['b', [1, 4]], ['c', [1, 3]]],
["choice3", ['b', [1, 2, 4]], ['c', [1, 2, 3, 4]]]
]
if 'a' is equal to '2' then the following function has to return "choice1" and "choice3" in the 'result':
function arraySearch(arr, a) {
var result = [];
for(var i = 0; i < arr.length; i++) {
// compare each arr[i] with 'a' for the very first occurrence, and move the next array
if(arr[i].search(a)){
result.concat(arr[0]);
}
}
return result;
}
Please help. Many thanks in advance.
something like
arr = [
["choice1", ['a', [2, 4]], ['b', [1, 3, 4]], ['c', [3, 4]]],
["choice2", ['b', [1, 4]], ['c', [1, 3]]],
["choice3", ['b', [1, 2, 4]], ['c', [1, 2, 3, 4]]]
];
find = function(arr, a) {
var found = [];
var foundCurrent;
// for each 'choice'
for (var choice = 0; choice < arr.length; choice++) {
foundCurrent = false;
// look at each entry in the array that is arr[current][1]
for (var entry = 1; entry < arr[choice].length; entry++) {
// search these for the value
if (arr[choice][entry][1].indexOf(a) != -1) {
if (!foundCurrent) {
found[found.length] = arr[choice][0];
}
foundCurrent = true;
}
}
}
return found;
};
find(arr, 2);
>> [choice1, choice3]
It's not clear to me exactly what you need.
If you want to know whether an array contains an element, use Array.indexOf.