Giving an object property an array value? - javascript

I have the following code and I want to make the deck array full of 52 different cards. Whenever I run the code and the card object is alerted it displays as '[object Object]'.
Can someone explain to me why it does this and a solution for this problem?
var suits = ["Clubs", "Diamonds", "Hearts", "Spades"];
var ranks = ["A", 2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K"];
var deck = [];
for (var i = 0; i < suits.length; i++) {
for (var j = 0; j < ranks.length; j++) {
var card = {rank: ranks[j], suit: suits[i]};
deck.push(card);
alert(card)
}
}

Why it does this
This is perfectly normal. The card object you create doesn't know how to represent itself when you do your alert(), simply because there are no toString() method implementation.
Solution for your problem
Try specifying an anonymous toString() function implementation to each card object like this:
var suits = ["Clubs", "Diamonds", "Hearts", "Spades"];
var ranks = ["A", 2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K"];
var deck = [];
for (var i = 0; i < suits.length; i++) {
for (var j = 0; j < ranks.length; j++) {
var card = {
rank: ranks[j],
suit: suits[i],
toString : function() { return this.rank + ' ' + this.suit; }
};
deck.push(card);
//alert(card); // console.log doesn't block code execution
console.log(card.toString());
}
}
Note
You should consider using console.log() instead of alert() as it is much less annoying and easier to debug in console (hit F12). But be careful with production code running IE9 or lower as their javascript engine will crash when the developper console is not opened.

This happens because you specify the entire object to alert, and alert does not know which properties are relevant. If you want an expandable view of your object, you can use console.log(card), this will output your object as a tree-view into the browser developer console.

That is how an object is showed, its toString method outputs just that, to see its contents use
alert(JSON.stringify(card));

You should change your alert to this:
alert(JSON.stringify(card))

FIDDLE DEMO
Replace your alert with this-->alert(JSON.stringify(card))
var suits = ["Clubs", "Diamonds", "Hearts", "Spades"];
var ranks = ["A", 2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K"];
var deck = [];
for (var i = 0; i < suits.length; i++) {
for (var j = 0; j < ranks.length; j++) {
var card = {rank: ranks[j], suit: suits[i]};
deck.push(card);
alert(JSON.stringify(card))//CHANGE THIS...
console.log(JSON.stringify(card))
}
}
EXPLANATION
JSON.stringify converts JavaScript data structures into JSON text.Json text is nothing but key:value pair of text.It cant get simpler.

Related

Better Algorithm for finding two elements in an array that sums up to the provided value

I am writing an algorithm for finding two elements in an array that sums up to the provided value. i.e for array [2, 7, 5, 3, 4, 11, 12, 56] and value 9 I am finding two elements for eg. 2 and 7 which adds to our provided value 9. I am getting the final result as [ [ 2, 7 ], [ 4, 5 ] ]. Please find the code below
const getSumOfValuesInArr = (arr, val) => {
var result = [];
for (var i = 0; i < arr.length; i++) {
for (var j = i; j < arr.length; j++) {
if (arr[j] + arr[i] === val) {
result.push([arr[i], arr[j]]);
}
}
}
console.log(result);
return result;
};
getSumOfValuesInArr([2, 7, 5, 3, 4, 11, 12, 56], 9);
But as you can it is a bit expensive. How can I write a better algorithm for better performance? Please help.
You could take a single loop and store seen values in a hash table.
Then check if the delta of the wanted sum and the actual value is seen before then add the pair to the result set.
const getSumOfValuesInArr = (arr, val) => {
var result = [],
seen = {};
for (let i = 0; i < arr.length; i++) {
if (seen[val - arr[i]]) result.push([val - arr[i], arr[i]]);
seen[arr[i]] = true;
}
return result;
};
console.log(getSumOfValuesInArr([2, 7, 5, 3, 4, 11, 12, 56], 9));

How to create an object from 2 arrays of same length

I am trying to create an object from 2 arrays.
var arr1 = ["2000", "10003", "1234000", "44444444", "9999", "11", "11", "22", "123"];
var arr2 = [2, 4, 10, 32, 36, 2, 2, 4, 6];
I used a for loop to populate the object:
var obj= {};
for(var i = 0; i < arr1.length; i++) {
obj[arr1[i]] = arr2[i];
}
Result:
[object Object] {
10003: 4,
11: 2,
123: 6,
1234000: 10,
2000: 2,
22: 4,
44444444: 32,
9999: 36
}
It does create the object based on my 2 arrays, but omit 1 value that is a duplicate in the arrays. I don't want to exclude them. What could be the trick to include ALL the array element in my object? The result is not even in the same order as the original arrays...
Thank you!
populate the values into array if that could be a workaround for you..
var obj= [];
for(var i = 0; i < arr1.length; i++) {
var obj1 ={};
obj1[arr1[i]] = arr2[i];
obj.push(obj1);
}

Array organization

I've been working with arrays and what I want is to create a formula that will allow me to loop over an array that contains objects and take keys with different values and turn them into a multi-dimensional array (I need to keep the order of the keys). I'm already getting this array but now I need to add ['n/a', '--'] on every position where the strings are not the same, like this:
var all = [
{banana: 1, rose: 2, mouse: 9, apple: 5, ana: 4, carl: 'truck'},
{banana: 1, rock: 58, car: 19, apple: 5, cheese: 3, carl: 'blue'},
{banana: 1, cheese: 2, red: 14, clue: 89, apple: 5, ana: 8}
];
//expected to get:
var new-arr = [ [["ana", 4], ["n/a", "--"], ["carl", "truck"]],
["n/a", "--"], ["cheese", 3], ["carl", "blue"]],
[["ana", 8], ["cheese", 2], ["n/a", "--"]] ];
So that at the end I cna create a list like this
list1:
ana: 4
n/a: --
carl: truck
list2:
n/a: --
cheese: 3
carl: blue
list2:
ana: 8
cheese: 2
n/a: --
The code is here
https://jsbin.com/yedusigara/1/edit?js,console
Did I do something wrong? Is there any way I can do it all in one function?
Your bug is not shown in the question, but it is in the fiddle, in this portion:
$('.lol').each(function (i, elm) {
similar_keys[i].forEach(function(spec, j){
similar_keys[j].forEach(function (spec1, j1){
if(spec[0] != spec1[0] && j != j1){
similar_keys[i].push(['n/a', '--']);
}
});
it doesn't make any sense to iterate through similar_keys[j] on the 3rd loop. j is an index of the inner array. This code just makes no sense. You even rely on having the same number of elements in the DOM and objects in your data.
I can only guess at what you are trying to accomplish, but I would modify your original algorithm instead. Maybe this:
function similars(arr) {
var similar_keys = [];
for (var i = 0; i < arr.length; i++) {
var tempArr = [];
for (var key in arr[i]) {
var found = false;
var count = 0;
var index = 0;
for (var j = 0; j < arr.length; j++) {
if (arr[j].hasOwnProperty(key)) {
++count;
}
if (i !== j && arr[j][key] === arr[i][key]) {
found = true;
break;
}
}
if (!found && count > 1) {
tempArr.push([key, arr[i][key]]);
}
else if (count > 1) {
tempArr.push(["N/A", arr[i][key]]);
}
}
similar_keys.push(tempArr);
}
return similar_keys;
}
EDIT:
Still not sure what you are looking for. What I think you need to do:
1) Sort each of the rows in similar_keys by the first element
2) Compare first element of each row, and insert the N/A entry to the row with the lowest sort order.
3) continue through each column, inserting as necessary.
i will try to modify your fiddle to demonstrate
EDIT:
this should work.
https://jsbin.com/nesiqogebo/edit?js,console,output

Better way to turn a one-dimensional array into multi-dimensional array by required group size in JS

I am rather new to JS and I was working on a problem that asked to split an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array.
I got the problem to work right for all test cases but it suggested using the array `push()` method. I tried it multiple times and couldn't ever get it to work right. I think I was getting messed up with arrays being by reference. I eventually declared a new Array for each element. I went with a more classic deep copy each element at a time. I Didn't go back and try the `push()` method again. There has to be a more efficient way to do this. I want to write good code. Would love to see better versions please.
Thanks!
function chunk(arr, size) {
var group = 0;
var counter = 0;
var even = false;
var odd = false;
if (arr.length % size === 0) {
group = arr.length / size;
even = true;
} else {
group = Math.ceil(arr.length / size);
odd = true;
}
var newArr = new Array(group);
for (var i = 0; i < group; i++) {
newArr[i] = new Array(size);
}
for (i = 0; i < group; i++) {
for (var j = 0; j < size && counter < arr.length; j++) {
newArr[i][j] = arr[counter++];
}
}
return newArr;
}
chunk(['a', 'b', 'c', 'd'], 2);
Using Array.prototype.slice, the function can be written in a shorter way:
function chunk(array, size) {
var result = []
for (var i=0;i<array.length;i+=size)
result.push( array.slice(i,i+size) )
return result
}
You can try the slice method from the Array object. Here's an idea on how to use it.
var arr = [1, 2, 3, 4, 5, 6];
var newArr = [];
newArr.push(arr.slice(0, arr.length / 2));
newArr.push(arr.length / 2, arr.length);
This is just an shallow implementation but you can use the same concept inside a better written function.
Here's an example function:
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
function toChunks(arr, size) {
var i = 0,
chunks = [];
for (; i < arr.length; i += size) {
chunks.push(arr.slice(i, i + size););
}
return chunks;
}
toChunks(arr, 2);

Best way to return duplicate elements in an Array

Here is the way I am using to return duplicate elements.. But I am facing most dangerous performance issues like browser close etc when my array have large number of items with long texts..
var arr = [9, 9, 111, 2, 3, 4, 4, 5, 7];
var sorted_arr = arr.sort();
var results = [];
for (var i = 0; i < arr.length - 1; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
results.push(sorted_arr[i]);
}
}
alert(results);
Please suggest me a best way of doing this
i don't get exactly what you want, but if you need to return duplicates you could use a cache object. this works with number or string or whatever.
var arr = [9, 9, 111, 2, 3, 4, 4, 5, 7];
var cache = {};
var results = [];
for (var i = 0, len = arr.length; i < len; i++) {
if(cache[arr[i]] === true){
results.push(arr[i]);
}else{
cache[arr[i]] = true;
}
}
console.log(results);//returns an array with 9 and 4
Of course you can do other things like deleting multiple items etc. etc.
EDIT - i've written a blog entry on how to remove duplicates from an array
If you have array filter, you also have indexOf and lastIndexOf,
and you can return the duplicates without doing the sort.
var results, arr= [9, 9, 111, 2, 3, 4, 4, 5, 4, 7];
if(arr.filter){
results= arr.filter(function(itm, i){
return arr.lastIndexOf(itm)== i && arr.indexOf(itm)!= i;
});
}
else// use your loop method
alert(results)
/* returned value: (Array)
9,4
*/
Assuming Nicola's solution doesn't work for you (since it uses about as much memory as the original solution: two elements stored per element in the input, worst-case), you can use the slower process of repeatedly searching your input.
This requires the Array.indexOf method from ECMAScript 5. A lot of browsers have it. For alternatives, see How do I check if an array includes an object in JavaScript?.
var arr = [9, 9, 111, 2, 3, 4, 4, 5, 7];
var results = [];
for (var i = 0, len = arr.length - 1; i < len; i++) {
if((results.indexOf(arr[i]) == -1) && (arr.indexOf(arr[i], i + 1) != -1)) {
results.push(arr[i]);
}
}
console.log(results);
This uses no more memory than the input arr plus the output results, but it's an O(N^2) algorithm and doesn't have to modify arr.
Your method relies on a sort, which may or may not be one reason you run out of space/time.
The canonical way to remove duplicates is to keep a hash map of the keys (an object in JS). The object keys you get back won't necessarily be in the order you want; you don't specify if you want the results ordered as well, but they are now.
You could null out the original array, since you no longer require it; when it gets collected is up to the JS engine though.
You could remove duplicates "in place" by keeping a "current index" into the sorted array, and increment it only when you move a non-duplicated element "down" from the counter index, then truncate the array that you return.
Combining the last two techniques should mean that in general you'll only have a single array with a valid reference.
Edit Example. Setting length explicitly, as .slice() creates a new array.
var have = {};
var arr = [9, 9, 111, 2, 3, 4, 4, 5, 7];
arr = arr.sort();
for (var rIdx = 0, i = 0; i < arr.length; i++) {
if (have[arr[i]]) {
arr[rIdx++] = arr[i];
} else {
have[arr[i]] = true;
}
}
arr.length = rIdx;
console.log(arr);

Categories