So I have 2 separate 2D array, they are not necessarily the same length, and I want to make an object for each. I made this:
var obj1 = {},
obj2 = {};
for (var i=0; i<arr1.length; i++) {
obj1[arr1[i][1]] = arr1[i][0];
}
for (var j=0; j<arr2.length; j++) {
obj2[arr2[j][1]] = arr2[j][0];
}
My question is if there is a way to make this with only one loop. Thanks!
You could try something like this:
var obj1 = {},
obj2 = {},
length = Math.max(arr1.length, arr2.length); // get max array length
for (var i = 0; i < length; i++) { // loop max array length
if (i < arr1.length) { // do check for arr1
obj1[arr1[i][1]] = arr1[i][0];
}
if (i < arr2.length) { // do check for arr2
obj2[arr2[i][1]] = arr2[i][0];
}
}
As pointed out, this may be less efficient than 2 separate loops,
Although it also may be more efficient
What you really want here is a function abstraction that removes the duplication. There is nothing to make this more efficient (if you meant time complexity, not developer efficiency):
function arrToObj(arr) {
var obj = {};
for (var i=0; i<arr.length; i++) {
obj[arr[i][1]] = arr[i][0];
}
return obj;
}
var obj1 = arrToObj(arr1),
obj2 = arrToObj(arr2);
The loop is still executed twice, but it's only written once.
Something like this should work:
var obj1 = {},
obj2 = {};
for (let i = 0; i < arr1.length && i < arr2.length; i++) {
obj1[arr1[i][1]] = arr1[i][0];
obj2[arr2[i][1]] = arr2[i][0];
}
if (arr1.length > arr2.length) {
for (let i = arr2.length; i < arr1.length; i++) {
obj1[arr1[i][1]] = arr1[i][0];
}
}
if (arr2.length > arr1.length) {
for (let i = arr1.length; i < arr2.length; i++) {
obj2[arr2[i][1]] = arr2[i][0];
}
}
Inspired by Pete's and eur00t's answers, I suggest this one:
var commonLength = Math.min(arr1.length, arr2.length);
for (var i = 0; i < commonLength; i++) {
obj1[arr1[i][1]] = arr1[i][0];
obj2[arr2[i][1]] = arr2[i][0];
}
for (var i = commonLength; i < arr1.length; i++) {
obj1[arr1[i][1]] = arr1[i][0];
}
for (var i = commonLength; i < arr2.length; i++) {
obj2[arr2[i][1]] = arr2[i][0];
}
As the question is about efficiency, I made a jsperf test case to compare the solutions.
var obj1 = {},
for (var i=0; i<arr1.length; i++) {
obj1[arr1[i][1]] = arr1[i][0];
}
for (var j=0; j<arr2.length; j++, i++) {
obj2[arr2[i][1]] = arr2[j][0];
}
Hope this will you
Related
I am trying to write an insertion sort function that works from right to left.
Not in descending order. I just am not understanding why this code would not properly sort numbers.
function reverseInsertionSort(arr) {
for(var i = arr.length -1; i >0; i--)
var val = arr[i];
var j;
for(j = i; j > 0 && arr[j-1] < val; j--) {
arr[j-1] = arr[j]; }
va=arr[j]; }
function insertionSort(arr) {
for(var i = 1; i < arr.length; i++) {
var val = arr[i];
var j;
for(j = i; j > 0 && arr[j-1] > val; j--) {
arr[j] = arr[j-1]; }
arr[j] = val; }
}
arr[j] = val;
}
}
var length = Math.floor(Math.random()*100)+1;
var arr = new Array();
for(let i = 0; i < length; i++) {
arr.push(Math.floor(Math.random()*10000)+1);
}
var arr2= arr.slice();
reverseInsertionSort(arr2);
console.log(arr2)
It is not sorted, and the output ends in undefined.
arr is being used to test the insertionsort fun
Happy to accept constructive criticism.
This will work.
function reverseInsertionSort(arr) {
for(var i = arr.length-2; i>=0; i--) {
var value = arr[i];
var j;
for(j = i; ((j < arr.length) && (arr[j+1] > value)); j++){
arr[j] = arr[j+1];
}
arr[j] = value;
}
return arr;
}
//test
var inputArray = [3,2,4,5,1,10,23];
var resultArray = reverseInsertionSort(inputArray);
console.log(resultArray); //[23, 10, 5, 4, 3, 2, 1]
You should start the outer loop from the last element ie. len-1. The undefined member of the array is created due to your outer loop starting from arr.length .
Try this :
function insSort(arr){
for(var i=arr.length-1;i>=0;i--){
key=arr[i];
j=i+1;
while(j<arr.length&&arr[j]<=key){
arr[j-1]=arr[j];
j++;
}
arr[j-1]=key;
}
}
var length = Math.floor(Math.random()*100)+1;
var arr = new Array();
for(let i = 0; i < length; i++) {
arr.push(Math.floor(Math.random()*10000)+1);
}
console.log(arr);
insSort(arr);
console.log(arr);
I have a function that has a nested for loop. As the function iterates over more data, it is starting to slow down. How can I best optimize this function so that it runs a bit faster?
function rubicoGVB(arr, range) {
var res = [];
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if ((arr[i] + arr[j]) / range < 16487665) {
res.push(arr[i]);
}
}
}
return res.length;
}
(The biggest improvement you could make is described by Fast Snail in this comment: You don't need the res array just to return its length; simply use a counter. Below are other improvements you could make.)
Looking at those loops, there's very little you can do other than:
Caching the length of the array, and
Caching arr[i] instead of looking it up repeated in the j loop
...which are minimal (but real) improvements, see len and entry below:
function rubicoGVB(arr, range) {
var res = [];
var len = arr.length;
var entry;
for (var i = 0; i < len; i++) {
entry = arr[i];
for (var j = i + 1; j < len; j++) {
if ((entry + arr[j]) / range < 16487665) {
res.push(entry);
}
}
}
return res.length;
}
The algorithm is taken from LeetCode: https://leetcode.com/problems/maximum-product-of-word-lengths/description/
Here is the jsperf I created (I have some local tests which gives the same result): https://jsperf.com/maximum-product-of-word-lengths
Here is the first "slow" implementation:
function maxProduct (words) {
if (!words || !words.length) return 0;
let len = words.length;
let values = [];
// console.log(values)
for (let i = 0; i < len; ++i) {
let tmp = words[i];
let num = 0, len = tmp.length;
for (let j = 0; j < len; ++j) {
num |= 1 << (tmp.charCodeAt(j) - 'a'.charCodeAt(0));
}
values[i] = {
num: num,
len: tmp.length
};
}
let maxProduct = 0;
for (let i = 0; i < len; ++i) {
for (let j = 0; j < len; ++j) {
if ((values[i].num & values[j].num) == 0) {
maxProduct = Math.max(maxProduct, values[i].len * values[j].len);
}
}
}
return maxProduct;
};
Here is the "fast" implementation:
function maxProductFast (words) {
var temp = [];
for(var i = 0; i < words.length; i++){
var tempObj = {};
tempObj.item = words[i];
var num = 0;
for(var j = 0; j < words[i].length; j++){
num |= 1 << (words[i].charCodeAt(j) - 97);
}
tempObj.num = num;
temp.push(tempObj);
}
var res = 0;
for(var i = 0; i < temp.length; i++){
for(var j = i + 1; j < temp.length; j++){
var item1 = temp[i];
var item2 = temp[j];
if((item1.num & item2.num) == 0) {
res = Math.max(res, item1.item.length * item2.item.length);
}
}
}
return res;
}
They're not the same. The second algorithm has a loop with a complexity of (n*(n+1))/2 where each progressive step is from i+1 to the length of temp. the first algorithm has a two nested for loops each with a cost of n^2. the complexity of both will reduce to O(n^2). I believe that both of these will have a similar performance with a significantly large enough set.
The reason you would do n+1 for each sub iteration is because you are trying to find the max of any pair of items. if you place your elements in a grid you will notice that any diagonal pair a_3 * a_2 = a_2 * a_3 produces the same value. you can basically halve the collection and save a few cycles.
Hi I am developing one jquery application. I am trying to compare the two arrays. For example,
Firstarray=["Mike","Jack"];
SecondArray=["Mike","Jack","Andy","Cruz"];
Whenever we compare above two arrays I want to return the strings which exists in both arrays or which are common to both arrays!
I tried as below. This piece of code is not working.
for (var i = 0; i < Firstarray.length; i++) {
for (var j = 0; j < SecondArray.length; j++) {
if (Firstarray[i] == SecondArray[j]) {
alert('found ' + SecondArray[j]);
return;
}
}
}
Can anyone help me in this regards! Thank you very much.
You can use indexOf() function
Firstarray=["Mike","Jack"];
SecondArray=["Mike","Jack","Andy","Cruz"];
var result = new Array();
for (var i = 0; i < Firstarray.length; i++) {
if(SecondArray.indexOf(Firstarray[i])>=0){
result.push(Firstarray[i]);
}
}
console.log(result);
Here is a solution using Array.prototype.filter and Array.prototype.some along with some ES6 flavor thrown in - see demo below:
var firstArray=["Mike","Jack"];
var secondArray=["Mike","Jack","Andy","Cruz"];
var result = secondArray.filter(a => firstArray.some(b => a === b));
console.log(result);
check this How can I find matching values in two arrays?
Array.prototype.diff = function(arr2) {
var ret = [];
this.sort();
arr2.sort();
for(var i = 0; i < this.length; i += 1) {
if(arr2.indexOf( this[i] ) > -1){
ret.push( this[i] );
}
}
return ret;
};
var FirstArray=["Mike","Jack"];
var SecondArray=["Mike","Jack","Andy","Cruz"];
var commonArray = Array();
var count=0;
for (var i=0; i<FirstArray.length; i++) {
for (var j=0;j< SecondArray.length;j++) {
if (FirstArray[i] == SecondArray[j]){
commonArray[count]=FirstArray[i];
count++;
}
}
}
console.log(commonArray);
Try changing few things in your code :
var Firstarray=["Mike","Jack"];
var SecondArray=["Mike","Jack","Andy","Cruz"];
var matchedData = [];
for (var i = 0; i < Firstarray.length; i++) {
for (var j = 0; j < SecondArray.length; j++) {
if (Firstarray[i] == SecondArray[j]) {
matchedData.push(SecondArray[j]);
}
}
}
alert(matchedData);
working fiddle :
https://jsfiddle.net/o3brcsvw/
try this
var Firstarray=["Mike","Jack"];
var SecondArray=["Mike","Jack","Andy","Cruz"];
var matchedData = [];
for (var i = 0; i < Firstarray.length; i++) {
for (var j = 0; j < SecondArray.length; j++) {
if (Firstarray[i] == SecondArray[j]) {
//alert('found ' + SecondArray[j]);
matchedData.push(SecondArray[j]);
}
}
}
return matchedData;
So that:
array = [[12,13,24],[24,22,11],[11,44,55]]
would return:
cleanedArray = [[12,13,24],[22,11],[44,55]]
I'm surprised not to have found this answered here.
var array = [[12,13,24],[24,22,11],[11,44,55]];
var output = [];
var found = {};
for (var i = 0; i < array.length; i++) {
output.push([]);
for (var j = 0; j < array[i].length; j++) {
if (!found[array[i][j]]) {
found[array[i][j]] = true;
output[i].push(array[i][j]);
}
}
}
console.log(output);
Are you looking for a function that does this for just two-dimensional arrays? If so, then I think this would work:
Array.prototype.clean = function()
{
var found = [];
for(var i = 0; i < this.length; i++)
{
for(var j = 0; j < this[i].length; j++)
{
if(found.indexOf(this[i][j]) != -1)
{
this[i].splice(j, 1);
}
else
{
found.push(this[i][j]);
}
}
}
return this;
};
If it's just a one-dimensional array you're looking for, then:
Array.prototype.clean = function()
{
var found = [];
for(var i = 0; i < this.length; i++)
{
if(found.indexOf(this[i]) != -1)
{
this.splice(i, 1);
}
else
{
found.push(this[i]);
}
}
return this;
};
this would work. If you're doing either of those, then do .clean() on your array to clean it up.
A simple function that modifies the original array is:
function removeDups(a) {
var item, j, found = {};
for (var i=0, iLen=a.length; i<iLen; i++) {
item = a[i];
j=item.length;
while (j--) {
found.hasOwnProperty(item[j])? item.splice(j,1) : found[item[j]] = '';
}
}
return a;
}