Javascript, repeating an object key N-times, being N its value - javascript

I was wondering how to do this in the more cleaner and optimal way:
I have an Object with the following structure:
{
"125": 2,
"439": 3,
"560": 1,
"999": 2,
...
}
I want to create a flat array repeating every key, the number of times indicated by its value. And bonus points for converting keys (strings) to integers. In this example, the resulting array should be:
[ 125, 125, 439, 439, 439, 560, 999, 999 ]
I've tried several ways but they all look over-engineered. For sure there is an easier way.
This is what I've got with underscore (and it returns an Array of strings, nor integers):
_.compact(_.flatten(_.map(files, function(num, id) {
return new Array(num+1).join('$'+id).split('$')
})))
I know there are plenty of ways to accomplish this. I just only want a clean and quick way. Being a Ruby developer it could be as easy as:
> files = {"125" => 2, "439" => 3, "560" => 1, "999" => 2}
=> {"125"=>2, "439"=>3, "560"=>1, "999"=>2}
> files.map {|key, value| [key.to_i] * value}.flatten
=> [125, 125, 439, 439, 439, 560, 999, 999]
Thanks in advance.

Try this:
var obj = {
"125": 2,
"439": 3,
"560": 1,
"999": 2
}
var arr = [];
for (prop in obj) {
for (var i = 0; i < obj[prop]; i++)
arr.push(parseInt(prop));
}
console.log(arr)

I know this is plain JavaScript but seems cleaner to me than the code you posted:
var dict = {
"125": 2,
"439": 3,
"560": 1,
"999": 2
}
var result = [];
for(key in dict)
for(i = 0; i < dict[key]; i++)
result.push(key * 1);
alert(result);

Hmm... not sure if I got at, but maybe something like this:
var myObj = {
"125": 2,
"439": 3,
"560": 1,
"999": 2
},
myArray = [];
for(k in myObj){
for(i = 0; i < myObj[k]; i++){
myArray.push(k);
}
}
console.log(myArray)

The problem with the other answers above is that the for..in language construct in javascript is going to involve all keys from the objects prototype chain. In this case, we should check and add only the correct keys.
var obj= {
"125": 2,
"439": 3,
"560": 1,
"999": 2
}
var arr=[];
for (var item in map) {
//important check!
if (map.hasOwnProperty(item)) {
arr.push(item);
}
}
Also see: http://www.yuiblog.com/blog/2006/09/26/for-in-intrigue/

Whether any of these approaches is cleaner is quite subjective:
// some helper function for creating an array with repeated values
function repeat(val, times) {
var arr = [];
for(var i = 0; i < times; i = arr.push(val));
return arr;
}
function convert(obj) {
var result = [], key;
for(key in obj) {
result = result.concat(repeat(+key, obj[key]));
}
return result;
}
Or a more functional approach:
Object.keys(obj).reduce(function(result, key) {
return result.concat(repeat(+key, obj[key]));
}, []);
// with underscore.js
_.reduce(_.keys(obj), function(result, key) {
return result.concat(repeat(+key, obj[key]));
}, []);

A helper function:
function flatten(obj){
//static Array method: create array (a elements, value b)
Array.aXb = Array.aXb || function(a,b){
b = b || 0;
return String(this(a)).split(',').map(function(){return b;});
}
//obj2array
var arr = [];
for (var k in obj)
if (+obj[k]) arr = arr.concat(Array.aXb(+obj[k],k));
return arr;
}
var obj= {"125": 2,"439": 3,
"560": 1,"999": 2 },
flatten(obj); //=> [125,125,439,439,439,560,999,999]

Related

JavaScript: Convert [a,b,c] into [a][b][c]

I have arrays like [a], [a,b], [a,b,c] and so on.
How can I convert them into [a], [a][b], [a][b][c] and so on?
Example:
var arr = [1,2,3,4];
arr = do(arr); // arr = arr[1][2][3][4]
You could map it with Array#map.That returns an array with the processed values.
ES6
console.log([1, 2, 3, 4].map(a => [a]));
ES5
console.log([1, 2, 3, 4].map(function (a) {
return [a];
}));
While the question is a bit unclear, and I think the OP needs possibly a string in the wanted form, then this would do it.
console.log([1, 2, 3, 4].reduce(function (r, a) {
return r + '[' + a + ']';
}, 'arr'));
Functional:
use .map like this
[1,2,3,4].map(i => [i])
Iterative:
var list = [1, 2, 3, 4], result = [];
for (var i=0; i<list.length; i++) {
result.push([list[i]]);
}
If I understand you correctly, you are converting single dimension array to multi dimensional array.
To do so,
var inputArray = [1,2,3,4];
var outputArray = [];
for(var i=0;i<inputArray.length;i++)
{
outputArray.push([inputArray[i]])
}
function map(arr){
var aux = [];
for(var i=0; i<arr.length;++i){
var aux2 = [];
aux2.push(arr[i]);
aux.push(aux2);
}
return aux;
}

Checking whether certain item is in certain array using javascript

I have 10 different arrays. Each array has different numbers.
array1 = [1,2,3,4,5]
array2 = [6,7,8,9,10]
...
array 10 = [51,52,53,54]
let's say I pass in 7. Then I want to know which array it is from and want to return array number. So in this case it is going to be 2.
Should I write a switch statement for each array? Appreciate it in javascript.
try:
var arrays = [array1, array2, ..., array10];
for(var i=0; i<arrays.length; ++i) {
if (arrays[i].indexOf(value) != -1) {
console.log('found in array' + (i+1));
}
}
You cannot directly retrieve the name of array.The reason is this variable is only storing a reference to the object.
Instead you can have a key inside the same array which represent its name. Then indexOf can be used to find the array which contain the number , & if it is so, then get the array name
var array1 = [1,2,3,4,5];
array1.name ="array1";
var array2 = [6,7,8,9,10];
array2.name ="array2";
var array10 = [51,52,53,54]
array10.name ="array10";
var parArray = [array1,array2,array10]
function _getArrayName(number){
for(var o=0;o<parArray.length;o++){
var _tem = parArray[o];
if(parArray[o].indexOf(number) !==-1){
console.log(parArray[o].name);
}
}
}
_getArrayName(6) //prints array2
jsfiddle
One fast method should be using hash tables or as i would like to call LUT. Accordingly this job boils down to a single liner as follows;
var arrs = {
arr1 : [1,2,3,4,5],
arr2 : [6,7,8,9,10],
arr3 : [12,14,16,17],
arr4 : [21,23,24,25,27,20],
arr5 : [31,34,35,39],
arr6 : [45,46,44],
arr7 : [58,59],
arr8 : [66,67,69,61],
arr9 : [72,73,75,79,71],
arr0 : [81,85,98,99,90,80]
},
lut = Object.keys(arrs).reduce((p,c) => {arrs[c].forEach(n => p[n]=c); return p},{}),
findar = n => lut[n];
document.write("<pre>" + findar(12) + "</pre>");
One way to do this is have the arrays in an object and iterate over the keys/values. This method doesn't presume the arrays (and therefore their names) are in sequential order.
Note: this will always return a the first match from the function and terminate the search.
var obj = {
array1: [1, 2, 3, 4, 5],
array2: [6, 7, 8, 9, 10],
array3: [51, 52, 53, 54],
array4: [51, 52, 53, 54, 7]
}
function finder(obj, test) {
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (obj[key].indexOf(test) > -1) {
return key.match(/\d+/)[0];
}
}
return false;
}
finder(obj, 7); // '2'
DEMO
If you want to find all instances of a value in all arrays the function needs to be altered slightly.
function finder(obj, test) {
var keys = Object.keys(obj);
var out = [];
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (obj[key].indexOf(test) > -1) {
out.push(key.match(/\d+/)[0]);
}
}
return out;
}
finder(obj, 7); // ['2', '4']
DEMO

fastest way to group keys with the same numeric value from a javascript object?

'Lets say I have an object
var obj = {
apples: 2,
grapes: 1,
oranges:2,
carrots:2,
potatoes: 4
}
how would I write a fast executing function that would return they keys grouped by their values?
return {
"2": ['apples', 'oranges', 'carrots'],
"4" : ['potatoes'],
"1" : ['grapes']
}
You can use a simple for..in to achieve this:
var obj = {
apples: 2,
grapes: 1,
oranges:2,
carrots:2,
potatoes: 4
};
var result = {};
for(var key in obj) {
if(!(obj[key] in result)) result[obj[key]] = [];
result[obj[key]].push(key);
}
console.log(result);
a quick and dirty function approach is interesting to contrast with the for loop:
var obj = {
apples: 2,
grapes: 1,
oranges:2,
carrots:2,
potatoes: 4
};
Object.keys(obj).reduce(function(a,b,k){
return (a[k=obj[b]]||(a[k]=[])).push(b), a;
},{});
there's less build up and tear-down, but the over-all effect is the same and for-loops might be more readable. either way, it's good to at least know about reduce() when facing many-into-one situations...
The for loop, but with a different syntax can as below seems to be little more faster(in chome & IE)
function convert3(obj) {
var ret = {}, arr;
for (var key in obj) {
arr = ret[obj[key]];
if (!arr) {
arr = ret[obj[key]] = [];
}
arr.push(key)
}
return ret;
}

Take highest property value and return it in an array in Javascript

I want to loop through this object and return the keys with the highest property values into an array.
Object {clear-spring: 3, deep-autumn: 2, warm-spring: 1, light-summer: 2, light-spring: 2, clear-summer: 3}
In this case, I want an array like this:
["clear-summer", "clear-spring"]
Is there an efficient way to do this with jQuery or pure javascript?
You simply need to iterate over your item once, keeping track of what ever the largest set is that you've found so far.
var a = {'clear-spring': 3, 'deep-autumn': 2, 'warm-spring': 1, 'light-summer': 2, 'light-spring': 2, 'clear-summer': 3};
var max = {
val: Number.NEGATIVE_INFINITY,
keys: []
}
for (var prop in a) {
if (a.hasOwnProperty(prop)) {
var n = a[prop];
if (n >= max.val) {
if (n > max.val) {
max.keys = [];
}
max.val = n;
max.keys.push(prop);
}
}
}
You may use for.. in to loop through the object
var object = {clear-spring: 3, deep-autumn: 2, warm-spring: 1, light-summer: 2, light-spring: 2, clear-summer: 3};
// Iterates over the oject
for (var key in object) {
if(object.hasOwnProperty(key)) {
// Key === 'clear-spring' (sample)
// object[key] === 3 (sample)
// do whatever you want
}
}
var o = {'clear-spring': 3, 'deep-autumn': 2, 'warm-spring': 1, 'light-summer': 2, 'light-spring': 2, 'clear-summer': 3};
var max = 0, result = [];
// find max:
for(var k in o) { if (o[k] > max) max = o[k] }
// find keys matching the max:
for(var k in o) { if (o[k] === max) result.push(k) }
// log result
console.log(result);
Not sure if most efficient, but first find the max value, then go back and pull out all the ones that match max value.
var obj = {'clear-spring': 3, 'deep-autumn': 2, 'warm-spring': 1, 'light-summer': 2, 'light-spring': 2, 'clear-summer': 3};
var ary = [];
var max = Number.NEGATIVE_INFINITY;
for (var prop in obj) {
if (obj[prop] > max) {
max = obj[prop];
}
}
for (var prop in obj) {
if (obj[prop] === max) {
ary.push(prop);
}
}

How can I reverse an array in JavaScript without using libraries?

I am saving some data in order using arrays, and I want to add a function that the user can reverse the list. I can't think of any possible method, so if anybody knows how, please help.
Javascript has a reverse() method that you can call in an array
var a = [3,5,7,8];
a.reverse(); // 8 7 5 3
Not sure if that's what you mean by 'libraries you can't use', I'm guessing something to do with practice. If that's the case, you can implement your own version of .reverse()
function reverseArr(input) {
var ret = new Array;
for(var i = input.length-1; i >= 0; i--) {
ret.push(input[i]);
}
return ret;
}
var a = [3,5,7,8]
var b = reverseArr(a);
Do note that the built-in .reverse() method operates on the original array, thus you don't need to reassign a.
Array.prototype.reverse() is all you need to do this work. See compatibility table.
var myArray = [20, 40, 80, 100];
var revMyArr = [].concat(myArray).reverse();
console.log(revMyArr);
// [100, 80, 40, 20]
Heres a functional way to do it.
const array = [1,2,3,4,5,6,"taco"];
function reverse(array){
return array.map((item,idx) => array[array.length-1-idx])
}
20 bytes
let reverse=a=>[...a].map(a.pop,a)
const original = [1, 2, 3, 4];
const reversed = [...original].reverse(); // 4 3 2 1
Concise and leaves the original unchanged.
reveresed = [...array].reverse()
The shortest reverse method I've seen is this one:
let reverse = a=>a.sort(a=>1)
**
Shortest reverse array method without using reverse method:
**
var a = [0, 1, 4, 1, 3, 9, 3, 7, 8544, 4, 2, 1, 2, 3];
a.map(a.pop,[...a]);
// returns [3, 2, 1, 2, 4, 8544, 7, 3, 9, 3, 1, 4, 1, 0]
a.pop method takes an last element off and puts upfront with spread operator ()
MDN links for reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop
two ways:
counter loop
function reverseArray(a) {
var rA = []
for (var i = a.length; i > 0; i--) {
rA.push(a[i - 1])
}
return rA;
}
Using .reverse()
function reverseArray(a) {
return a.reverse()
}
This is what you want:
array.reverse();
DEMO
Here is a version which does not require temp array.
function inplaceReverse(arr) {
var i = 0;
while (i < arr.length - 1) {
arr.splice(i, 0, arr.pop());
i++;
}
return arr;
}
// Useage:
var arr = [1, 2, 3];
console.log(inplaceReverse(arr)); // [3, 2, 1]
I've made some test of solutions that not only reverse array but also makes its copy. Here is test code. The reverse2 method is the fastest one in Chrome but in Firefox the reverse method is the fastest.
var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var reverse1 = function() {
var reversed = array.slice().reverse();
};
var reverse2 = function() {
var reversed = [];
for (var i = array.length - 1; i >= 0; i--) {
reversed.push(array[i]);
}
};
var reverse3 = function() {
var reversed = [];
array.forEach(function(v) {
reversed.unshift(v);
});
};
console.time('reverse1');
for (var x = 0; x < 1000000; x++) {
reverse1();
}
console.timeEnd('reverse1'); // Around 184ms on my computer in Chrome
console.time('reverse2');
for (var x = 0; x < 1000000; x++) {
reverse2();
}
console.timeEnd('reverse2'); // Around 78ms on my computer in Chrome
console.time('reverse3');
for (var x = 0; x < 1000000; x++) {
reverse3();
}
console.timeEnd('reverse3'); // Around 1114ms on my computer in Chrome
53 bytes
function reverse(a){
for(i=0,j=a.length-1;i<j;)a[i]=a[j]+(a[j--]=a[i++],0)
}
Just for fun, here's an alternative implementation that is faster than the native .reverse method.
You can do
var yourArray = ["first", "second", "third", "...", "etc"]
var reverseArray = yourArray.slice().reverse()
console.log(reverseArray)
You will get
["etc", "...", "third", "second", "first"]
> var arr = [1,2,3,4,5,6];
> arr.reverse();
[6, 5, 4, 3, 2, 1]
array.reverse()
Above will reverse your array but modifying the original.
If you don't want to modify the original array then you can do this:
var arrayOne = [1,2,3,4,5];
var reverse = function(array){
var arrayOne = array
var array2 = [];
for (var i = arrayOne.length-1; i >= 0; i--){
array2.push(arrayOne[i])
}
return array2
}
reverse(arrayOne)
function reverseArray(arr) {
let reversed = [];
for (i = 0; i < arr.length; i++) {
reversed.push((arr[arr.length-1-i]))
}
return reversed;
}
Using .pop() method and while loop.
var original = [1,2,3,4];
var reverse = [];
while(original.length){
reverse.push(original.pop());
}
Output: [4,3,2,1]
I'm not sure what is meant by libraries, but here are the best ways I can think of:
// return a new array with .map()
const ReverseArray1 = (array) => {
let len = array.length - 1;
return array.map(() => array[len--]);
}
console.log(ReverseArray1([1,2,3,4,5])) //[5,4,3,2,1]
// initialize and return a new array
const ReverseArray2 = (array) => {
const newArray = [];
let len = array.length;
while (len--) {
newArray.push(array[len]);
}
return newArray;
}
console.log(ReverseArray2([1,2,3,4,5]))//[5,4,3,2,1]
// use swapping and return original array
const ReverseArray3 = (array) => {
let i = 0;
let j = array.length - 1;
while (i < j) {
const swap = array[i];
array[i++] = array[j];
array[j--] = swap;
}
return array;
}
console.log(ReverseArray3([1,2,3,4,5]))//[5,4,3,2,1]
// use .pop() and .length
const ReverseArray4 = (array) => {
const newArray = [];
while (array.length) {
newArray.push(array.pop());
}
return newArray;
}
console.log(ReverseArray4([1,2,3,4,5]))//[5,4,3,2,1]
As others mentioned, you can use .reverse() on the array object.
However if you care about preserving the original object, you may use reduce instead:
const original = ['a', 'b', 'c'];
const reversed = original.reduce( (a, b) => [b].concat(a) );
// ^
// |
// +-- prepend b to previous accumulation
// original: ['a', 'b', 'c'];
// reversed: ['c', 'b', 'a'];
Pure functions to reverse an array using functional programming:
var a = [3,5,7,8];
// ES2015
function immutableReverse(arr) {
return [ ...a ].reverse();
}
// ES5
function immutableReverse(arr) {
return a.concat().reverse()
}
It can also be achieved using map method.
[1, 2, 3].map((value, index, arr) => arr[arr.length - index - 1])); // [3, 2, 1]
Or using reduce (little longer approach)
[1, 2, 3].reduce((acc, curr, index, arr) => {
acc[arr.length - index - 1] = curr;
return acc;
}, []);
reverse in place with variable swapping (mutative)
const myArr = ["a", "b", "c", "d"];
for (let i = 0; i < (myArr.length - 1) / 2; i++) {
const lastIndex = myArr.length - 1 - i;
[myArr[i], myArr[lastIndex]] = [myArr[lastIndex], myArr[i]]
}
Reverse by using the sort method
This is a much more succinct method.
const resultN = document.querySelector('.resultN');
const resultL = document.querySelector('.resultL');
const dataNum = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const dataLetters = ['a', 'b', 'c', 'd', 'e'];
const revBySort = (array) => array.sort((a, b) => a < b);
resultN.innerHTML = revBySort(dataNum);
resultL.innerHTML = revBySort(dataLetters);
<div class="resultN"></div>
<div class="resultL"></div>
Using ES6 rest operator and arrow function.
const reverse = ([x, ...s]) => x ? [...reverse(s), x] : [];
reverse([1,2,3,4,5]) //[5, 4, 3, 2, 1]
Use swapping and return the original array.
const reverseString = (s) => {
let start = 0, end = s.length - 1;
while (start < end) {
[s[start], s[end]] = [s[end], s[start]]; // swap
start++, end--;
}
return s;
};
console.log(reverseString(["s", "t", "r", "e", "s", "s", "e", "d"]));
Infact the reverse() may not work in some cases, so you have to make an affectation first as the following
let a = [1, 2, 3, 4];
console.log(a); // [1,2,3,4]
a = a.reverse();
console.log(a); // [4,3,2,1]
or use concat
let a = [1, 2, 3, 4];
console.log(a, a.concat([]).reverse()); // [1,2,3,4], [4,3,2,1]
What about without using push() !
Solution using XOR !
var myARray = [1,2,3,4,5,6,7,8];
function rver(x){
var l = x.length;
for(var i=0; i<Math.floor(l/2); i++){
var a = x[i];
var b = x[l-1-i];
a = a^b;
b = b^a;
a = a^b;
x[i] = a;
x[l-1-i] = b;
}
return x;
}
console.log(rver(myARray));
JavaScript already has reverse() method on Array, so you don't need to do that much!
Imagine you have the array below:
var arr = [1, 2, 3, 4, 5];
Now simply just do this:
arr.reverse();
and you get this as the result:
[5, 4, 3, 2, 1];
But this basically change the original array, you can write a function and use it to return a new array instead, something like this:
function reverse(arr) {
var i = arr.length, reversed = [];
while(i) {
i--;
reversed.push(arr[i]);
}
return reversed;
}
Or simply chaning JavaScript built-in methods for Array like this:
function reverse(arr) {
return arr.slice().reverse();
}
and you can call it like this:
reverse(arr); //return [5, 4, 3, 2, 1];
Just as mentioned, the main difference is in the second way, you don't touch the original array...
How about this?:
function reverse(arr) {
function doReverse(a, left, right) {
if (left >= right) {
return a;
}
const temp = a[left];
a[left] = a[right];
a[right] = temp;
left++;
right--;
return doReverse(a, left, right);
}
return doReverse(arr, 0, arr.length - 1);
}
console.log(reverse([1,2,3,4]));
https://jsfiddle.net/ygpnt593/8/

Categories

Resources