How to double the numbers in an array of objects? - javascript

I want to double the key values in an array of objects and I always end up getting the last key:val in the list. I want to be able to print the whole array of objects doubled their values.
doubleArr = [];
function doubleSize (a,b) {
for(var i in a) {
if (a.hasOwnProperty(i)) {
var doubleObj = {};
doubleObj[i] = b * a[i];
var results = doubleObj[i];
doubleArr.push(results);
}
}
return doubleObj;
}
console.log(doubleSize({1:1,1:2,1:3,1:4,1:5}, 2))
I only get {1:10}. The goal is to get {1:2,1:4,1:6,1:8,1:10}. Thanks.

The primary issue with your code is that you cannot have duplicate keys in an object. Every key in an object must be unique; otherwise, you are essentially redeclaring the value associated with that key over and over (so, naturally, in your example, the key 1 will end up being associated with the last value you assign it: 5).
However, even if you used an object without duplicate keys, you still have the following issues:
Your doubleArr should not be declared in the global scope, but instead within the function; moreover, you don't need an array for what you're doing
Your code is actually constructing an array of objects rather than an object. If you want to return an object, you should build up an object with unique values in your function.
Here's an example of a modified version of your code:
function doubleSize (a,b) {
var doubleObj = {};
for(var i in a) {
if (a.hasOwnProperty(i)) {
doubleObj[i] = b * a[i];
}
}
return doubleObj;
}
console.log(doubleSize({1:1,2:2,3:3,4:4,5:5}, 2)) // Note the unique keys
However, I don't fully understand the need for objects. You could use arrays instead, and then replace all of your code with a simple one-liner using Array.map:
var arr = [1, 2, 3, 4, 5]
var doubledArr = arr.map(x => 2*x) // An arrow function that multiplies each value in the array by 2
console.log(doubledArr)

You are using the same key for your objects 1. I am assuming that you don't need objects as they don't provide anything obvious to your code:
Edit If you insist on using objects, I have provided the second version also.
function doubleSize (a,b)
{
var doubleArr = [];
for(var i=0; i<a.length;i++)
{
doubleArr.push(a[i]*b);
}
return doubleArr;
}
console.log(doubleSize([1,2,3,4,5], 2))
function doubleSize2 (a,b)
{
var result = {};
for(var i in a)
{
result[i] = a[i]*b
}
return result;
}
console.log(doubleSize2({a:1,b:2,c:3,d:4,e:5}, 2))

You can't have duplicate keys in an object, you can have an array of objects with the same key though. Something like:
function doubleSize (a, b) {
var out = [];
for(var i = 0; i < a.length; i++) {
out.push({'1': a[i]['1'] * b});
}
return out;
}
console.log(doubleSize([{'1': 1}, {'1': 2}, {'1': 3}, {'1': 4}, {'1': 5}], 2));

function doubleSize (a,b) {
var midObject = {};
for(var i in a) {
if (a.hasOwnProperty(i)) {
midObject[i] = b * a[i];
}
}
return midObject;
}
console.log(doubleSize({1:1,2:2,3:3,4:4,5:5}, 5))

Related

Arrange array like gaussian function (max values in middle, min values in edges)

How can I arrange an array like a gaussian function, meaning max values in the middle, min values in edges?
e.g.
var Array = [5,2,7,4,1]
will output the following array:
[1,4,7,5,2]
I didn't used underscore functions but you can use equivalent function from underscore/lodash to shorten code.
Steps:
Sort the array in descending order
Iterate over array and add the elements from sorted array at the start and end alternately
var arr = [5, 2, 7, 4, 1];
var sortedArr = arr.sort(function(a, b) {
return b - a;
});
var gaussianArr = [];
sortedArr.forEach(function(e, i) {
if (i % 2) {
gaussianArr.push(e);
} else {
gaussianArr.unshift(e);
}
});
console.log(gaussianArr);
document.write(gaussianArr);
Want underscore solution?
Here you go. fiddle. You won't see much difference between Vanilla JS solution and underscore solution(as the logic is same, only different syntax).
Here is the logic.
function gSort(arr) {
var _a = arr.slice()
_a.sort(function(a,b){return a-b});
_a.reverse();
var _isstart = false;
var _out = [];
for (var i = 0; i < _a.length; i++) {
if (i%2) {
_out.push(_a[i])
}else{
_out.splice(0,0,_a[i]); //You can use _out.unshift(_a[i]); also
}
}
return _out;
}
var array = [5,2,7,4,1]
console.log(gSort(array));

Retrieving all values from a JavaScript object

This is the function I wrote to retrieve all the values in an given object.
function getValues(data){
var keys = Object.keys(data);
var values = [];
for(var i = 0, l = keys.length, key; i< l; i++){
key = keys[i];
values.push(data[key]);
}
return values;
}
Is there any builtin way to retrieve all the values in an object? Something like this exists in java for HashMaps. I know JS has a method for retrieving all the keys by doing Object.keys(obj).
Probably the most concise way of getting an array of the values contained within an object is to use Object.keys and Array.prototype.map:
obj = {
a: 1,
b: 2,
c: 3
};
values = Object.keys(obj).map(function (key) {
return obj[key];
});
Otherwise there's no standardized way of getting an array of an object's values.
For iterating, ES6 introduces a for..of loop which will iterate through an object's values:
continued from above:
for (value of obj) {
console.log(value); //1, 2, 3
}
ES7 is slated to introduce array comprehensions, so generating the values array could be written as:
continued from above:
values = [for (x of Object.keys(obj)) obj[x]];
If you're already using underscore, you can use the _.values method:
continued from above:
_.values(obj); //[1, 2, 3]
If you just want an efficient implementation for this utility function, the lodash source is:
lodash.js v2.4.1 lines 2891-2914
/**
* Creates an array composed of the own enumerable property values of `object`.
*
* #static
* #memberOf _
* #category Objects
* #param {Object} object The object to inspect.
* #returns {Array} Returns an array of property values.
* #example
*
* _.values({ 'one': 1, 'two': 2, 'three': 3 });
* // => [1, 2, 3] (property order is not guaranteed across environments)
*/
function values(object) {
var index = -1,
props = keys(object),
length = props.length,
result = Array(length);
while (++index < length) {
result[index] = object[props[index]];
}
return result;
}
You could do this, in newer Browsers:
Object.defineProperty(Object.prototype, 'values', {
get:function(){
return function(o){
var a = [];
for(var i in o){
a.push(o[i]);
}
return a;
}
}
});
var arrayOfValues = Object.values({a:'A',b:'B',c:'C'});
Really, I would just do:
function objectValues(obj, inherited){
var a = [];
for(var i in obj){
var v = obj[i];
if(inherited){
a.push(v);
}
else if(obj.hasOwnProperty(i)){
a.push(v);
}
}
return a;
}
var notInheritedArrayOfValues = objectValues({a:'A',b:'B',c:'C'});
var inheritedArrayOfValues = objectValues({a:'A',b:'B',c:'C'}, true);

Get the array index of duplicates

In a JavaScript array how can I get the index of duplicate strings?
Example:
MyArray = ["abc","def","abc"]; //----> return 0,2("abc");
Another example:
My Array = ["abc","def","abc","xyz","def","abc"]
//----> return 0,2,5("abc") and 1,4("def");
I have no idea how to do this.
Thanks in advance for your help!
Update 01/2022: It's not 2013 anymore, and many things have changed. I neither recommend modifying the prototype, nor is the approach in this answer the "best" as it requires several iterations over the array.
Here's an updated version of the original answer, retaining its spirit, as well as the original answer below.
function getDuplicates<T>(input: T[]): Map<T, number[]> {
return input.reduce((output, element, idx) => {
const recordedDuplicates = output.get(element);
if (recordedDuplicates) {
output.set(element, [...recordedDuplicates, idx]);
} else if (input.lastIndexOf(element) !== idx) {
output.set(element, [idx]);
}
return output;
}, new Map<T, number[]>());
}
Yet another approach:
Array.prototype.getDuplicates = function () {
var duplicates = {};
for (var i = 0; i < this.length; i++) {
if(duplicates.hasOwnProperty(this[i])) {
duplicates[this[i]].push(i);
} else if (this.lastIndexOf(this[i]) !== i) {
duplicates[this[i]] = [i];
}
}
return duplicates;
};
It returns an object where the keys are the duplicate entries and the values are an array with their indices, i.e.
["abc","def","abc"].getDuplicates() -> { "abc": [0, 2] }
Another less sophisticated approach:
Iterate over the whole array and keep track of the index of each element. For this we need a string -> positions map. An object is the usual data type to use for this. The keys are the elements of the array and the values are arrays of indexes/positions of each element in the array.
var map = {};
for (var i = 0; i < arr.length; i++) {
var element = arr[i]; // arr[i] is the element in the array at position i
// if we haven't seen the element yet,
// we have to create a new entry in the map
if (!map[element]) {
map[element] = [i];
}
else {
// otherwise append to the existing array
map[element].push(i);
}
// the whole if - else statement can be shortend to
// (map[element] || (map[element] = [])).push(i)
}
Now you can iterate over the map and remove all entries where the array value has a length of one. Those are elements that appear only once in an array:
for (var element in map) {
if (map[element].length === 1) {
delete map[element];
}
}
Now map contains a string -> positions mapping of all duplicate elements of the array. For example, if you array is ["abc","def","abc","xyz","def","abc"], then map is an object of the form
var map = {
'abc': [0,2,5],
'def': [1,4]
};
and you can process it further in any way you like.
Further reading:
Eloquent JavaScript - Data structures: Objects and Arrays
MDN - Working with objects
MDN - Predefined core objects, Array object
This covers finding the indices efficiently:
var inputArray = [1, 2, 3, 4, 5, 6, 6, 7, 8, 9];
var encounteredIndices = {};
for(var i = 0; i < inputArray.length; i++)
if (encounteredIndices[inputArray[i]])
console.log(i); // Or add to some array if you wish
else
encounteredIndices[inputArray[i]] = 1;

Shuffling array properties in JavaScript

I have a data dictionary like this:
var data = {
'text1': 1,
'text2': 2,
'text3': 3,
...
'text20': 20
];
I need to pick a random selection of those keys and then shuffle it's values. In the example, it should write something like this:
> console.log(choose(data, 5));
[ { key: 'text15', value: 8 },
{ key: 'text6', value: 3 },
{ key: 'text3', value: 15 },
{ key: 'text19', value: 6 },
{ key: 'text8', value: 19 } ]
For now I'm extracting the keys into another array and sorting by Math.random() but I'm stuck at swaping the values because no key should have the same value it initially had.
How would you swap key/values here?
Thanks
I put together a possible solution using underscore.js to simplify traversing the object and arrays in a cross browser manner:
var data = {
text1: 1,
text2: 2,
text3: 3,
text4: 4,
text5: 5,
text6: 6,
text7: 7,
text8: 8,
text9: 9,
text10: 10
};
function choose(data, num)
{
var keys = _.sortBy(
_.keys(data),
function(k)
{
return (Math.random() * 3) - 1;
}
),
results = [],
k1, k2;
if (num > keys.length) {
throw new Error('Impossible to retrieve more values than exist');
}
while (results.length < num) {
k1 = k2 || keys.pop();
k2 = keys.pop();
results.push({key:k1, value: data[k2]});
}
return results;
}
console.log(choose(data, 5));
This isn't necessarily an optimal approach but it seems to meet your requirements. I first grab all of the keys and sort them randomly. I then loop through the random keys creating a new object with one key and the following keys value. That way you'll always end up with a different value associated with each key. If you need it to work when the value of num passed in to the function == the number of keys in the data then you'll have to add a little more code - I'll leave that as an exercise for the reader :)
You can have a play with this code on jsfiddle:
http://jsfiddle.net/zVyQW/1/
You could do this:
collect names and corresponding values in two arrays names and values
shuffle both arrays independently of each other
take the first n items of both arrays and combine them
Here’s an example implementation:
Array.prototype.shuffle = function() {
for (var i=this.length-1, j, tmp; i>0; i--) {
j = Math.round(Math.random()*i);
tmp = this[i], this[i] = this[j], this[j] = tmp;
}
return this;
};
function choose(data, number) {
var names = [], values = [], pick = [];
for (var name in data) {
if (data.hasOwnProperty(name)) {
names.push(name);
values.push(data[name]);
}
}
names = names.shuffle(), values = values.shuffle();
for (var i=Math.min(number >>> 0, names.length-1); i>=0; i--) {
pick.push({key: names[i], value: values[i]});
}
return pick;
}
Been a while since this was answered, but I was working on shuffling and found the following to be by far the fastest implementation with an evenly random distribution.
It's fast because it only makes one call to Math.random on each iteration, all the rest is done by property access. It doesn't modify the array, just reassigns values.
function shuffle(a) {
var t, j, i=a.length, rand=Math.random;
// For each element in the array, swap it with a random
// element (which might be itself)
while (i--) {
k = rand()*(i+1)|0;
t = a[k];
a[k]=a[i];
a[i]=t;
}
return a;
}
It uses a combination of three functions (including the Array shuffle prototype method).
Here is the complete code:
var obj = {
"red":"RED",
"blue":"BLUE",
"green":"GREEN",
"yellow":"YELLOW",
"purple":"PURPLE"
};
Array.prototype.shuffle = function(){
for (var i = 0; i < this.length; i++){
var a = this[i];
var b = Math.floor(Math.random() * this.length);
this[i] = this[b];
this[b] = a;
}
}
obj = shuffleProperties(obj); // run shuffle
function shuffleProperties(obj) {
var new_obj = {};
var keys = getKeys(obj);
keys.shuffle();
for (var key in keys){
if (key == "shuffle") continue; // skip our prototype method
new_obj[keys[key]] = obj[keys[key]];
}
return new_obj;
}
function getKeys(obj){
var arr = new Array();
for (var key in obj)
arr.push(key);
return arr;
}
for(key in obj){
alert(key);
}
Check all post,
Best Regards.
Use an implementation of random that randomizes a discrete set of values, such as Math.rand seen here. For each index, randomize Math.rand(index, length-1) to get a list of random indexes, the location off all indices will change.

Combaining two array into single multi dimensional array in javascript

status_name=Array("a","b","c","b","e","f");
status_id=Array( 1, 2, 3, 4, 5, 6);
How to combine these two arrays and to built multi dimensional array Expected Multidimensional array be like this
[["a", 1],["b", 2],["c", 3],["d", 4],["e", 5],["f", 6]]
Help me how to use above two array values and built my expected multidimensional array
Since you're including jQuery, you can use jQuery.map in a similar fashion to Linus' answer:
var result = [],
status_name = ["a","b","c","b","e","f"],
status_id = [1, 2, 3, 4, 5, 6];
result = $.map(status_name, function (el, idx) {
return [[el, status_id[idx]]];
});
Looking at your variable names, I'd guess that your coming from a language (like PHP). If that's the case, make sure you remember to declare local variables with the var keyword, otherwise you'll be polluting the global scope and you'll run into some hideous bugs in IE.
JavaScript has no buitin method for this, but you can easily write it yourself:
function zip(arrayA, arrayB) {
var length = Math.min(arrayA.length, arrayB.length);
var result = [];
for (var n = 0; n < length; n++) {
result.push([arrayA[n], arrayB[n]]);
}
return result;
}
The name zip is chosen because a function that does something like this is often called zip in other languages.
I tried Myself and brought this solution, It might help some one
status_name=Array("a","b","c","b","e","f");
status_id=Array( 1, 2, 3, 4, 5, 6);
Script:
Values=[];
for (i = 0; i < status_name.length; ++i)
{
Values[i] =Array(status_name[i], status_id[i]);
}
Using jQuery.map
var status_name = ["a","b","c","b","e","f"],
status_id = [1,2,3,4,5,6],
r = [];
r = $.map(status_name, function(n, i) {
return [[n, status_id[i]]];
});
Note the difference between return [[n, status_id[i]]] and return [n, status_id[i]]. Using the former will result in a 2d array while using the latter will result in a 1d array.
var combined = [], length = Math.min(status_name.length, status_id.length);
for(var i = 0; i < length; i++) {
combined.push([status_name[i], status_id[i]]);
}
You could also use Array.prototype.map, but that's not supported in all browsers:
var combined = status_name.map(function(name, index) { return [name, status_id[index]] });
try
function array_combine (keys, values) {
// Creates an array by using the elements of the first parameter as keys and the elements of the second as the corresponding values
//
// version: 1102.614
// discuss at: http://phpjs.org/functions/array_combine
// + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + improved by: Brett Zamir (http://brett-zamir.me)
// * example 1: array_combine([0,1,2], ['kevin','van','zonneveld']);
// * returns 1: {0: 'kevin', 1: 'van', 2: 'zonneveld'}
var new_array = {},
keycount = keys && keys.length,
i = 0;
// input sanitation
if (typeof keys !== 'object' || typeof values !== 'object' || // Only accept arrays or array-like objects
typeof keycount !== 'number' || typeof values.length !== 'number' || !keycount) { // Require arrays to have a count
return false;
}
// number of elements does not match
if (keycount != values.length) {
return false;
}
for (i = 0; i < keycount; i++) {
new_array[keys[i]] = values[i];
}
return new_array;
Reference
- arr combine
- array combine

Categories

Resources