Array organization - javascript

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

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));

Delete numbers below a certain number in an array

Today i'm facing a really weird problem.
I'm actually trying to delete numbers below a certain number in an array.
I have this array [1, 7, 2, 3, 90, 4, 70, 20] and I only want the numbers greater than 20 !
So I should have that in output : [90, 70]
But Instead I have this array : [7, 3, 90, 70, 20] ???
Here is my code :
function superior() {
var arr = [1, 7, 2, 3, 90, 4, 70, 20]
for (var i = 0; i < arr.length; i++) {
if (arr[i] < 20) {
arr.splice(arr.indexOf(arr[i]), 1);
} else {
break;
}
}
return arr;
}
console.log(superior());
Mutating an array while you're looping through it is always going to be tricky. If you shrink the size of the array, but don't change i, then you're can end up interacting with the wrong element of the array the next time through the loop. Also, using break will stop the loop from running entirely, and so skip the rest of the array. You may have meant to use continue, but since you're on the last line of the loop anyway, continue isn't needed.
Rather than trying to change the array and loop through it at the same time, i'd recommend creating a new array. Then you can loop through the old one unhindered:
const arr = [1, 7, 2, 3, 90, 4, 70, 20]
const newArr = []
for (const i = 0; i < arr.length; i++) {
if (arr[i] >= 20) {
newArr.push(arr[i]);
}
}
console.log(newArr)
Filtering an array like this is a very common thing to do, so there are built in tools to do it for you. Every array has a .filter method. You pass into it a function describing what elements you want to keep, and it will produce the new array for you:
const arr = [1, 7, 2, 3, 90, 4, 70, 20]
const newArr = arr.filter(element => element >= 20);
console.log(newArr)
You can filter them out according to a condition.
And replace your existing array with the filtered one. Or if you don't want to replace it, use another variable and assign the filtered value to that variable.
var newArray = array.filter(item => item > 20)
Check .filter()
var array = [1, 7, 2, 3, 90, 4, 70, 20];
array = array.filter(item => item > 20)
console.log(array)
You can use Array.filter()
var arr = [1, 7, 2, 3, 90, 4, 70, 20]
var filteredArr = arr.filter(item => item > 20);
console.log(filteredArr);
You could iterate from the end and omit indexOf, because you have already the index i.
This appoach loops from the end and after splicing, the remaining lower indices remains.
function superior() {
var array = [1, 7, 2, 3, 90, 4, 70, 20],
i = array.length;
while (i--) if (array[i] < 20) array.splice(i, 1);
return array;
}
console.log(superior());
Use temporary array to push new values.
function superior() {
var arr = [1, 7, 2, 3, 90, 4, 70, 20];
temp_arr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] > 20) {
temp_arr.push(arr[i]);
}
}
return temp_arr;
}
console.log(superior());

Find the first repeated number in a Javascript array

I need to find first two numbers and show index like:
var arrWithNumbers = [2,5,5,2,3,5,1,2,4];
so the first repeated number is 2 so the variable firstIndex should have value 0. I must use for loop.
var numbers = [7, 5, 7, 6, 6, 4, 9, 10, 2, 11];
var firstIndex
for (i = numbers[0]; i <= numbers.length; i++) {
firstIndex = numbers[0]
if (numbers[i] == firstIndex) {
console.log(firstIndex);
break;
}
}
You can use Array#indexOf method with the fromIndex argument.
var numbers = [7, 5, 7, 6, 6, 4, 9, 10, 2, 11];
// iterate upto the element just before the last
for (var i = 0; i < numbers.length - 1; i++) {
// check the index of next element
if (numbers.indexOf(numbers[i], i + 1) > -1) {
// if element present log data and break the loop
console.log("index:", i, "value: ", numbers[i]);
break;
}
}
UPDATE : Use an object to refer the index of element would make it far better.
var numbers = [7, 5, 7, 6, 6, 4, 9, 10, 2, 11],
ref = {};
// iterate over the array
for (var i = 0; i < numbers.length; i++) {
// check value already defined or not
if (numbers[i] in ref) {
// if defined then log data and brek loop
console.log("index:", ref[numbers[i]], "value: ", numbers[i]);
break;
}
// define the reference of the index
ref[numbers[i]] = i;
}
Many good answers.. One might also do this job quite functionally and efficiently as follows;
var arr = [2,5,5,2,3,5,1,2,4],
frei = arr.findIndex((e,i,a) => a.slice(i+1).some(n => e === n)); // first repeating element index
console.log(frei)
If might turn out to be efficient since both .findIndex() and .some() functions will terminate as soon as the conditions are met.
You could use two for loops an check every value against each value. If a duplicate value is found, the iteration stops.
This proposal uses a labeled statement for breaking the outer loop.
var numbers = [1, 3, 6, 7, 5, 7, 6, 6, 4, 9, 10, 2, 11],
i, j;
outer: for (i = 0; i < numbers.length - 1; i++) {
for (j = i + 1; j < numbers.length; j++) {
if (numbers[i] === numbers[j]) {
console.log('found', numbers[i], 'at index', i, 'and', j);
break outer;
}
}
}
Move through each item and find if same item is found on different index, if so, it's duplicate and just save it to duplicate variable and break cycle
var numbers = [7, 5, 7, 6, 6, 4, 9, 10, 2, 11];
var duplicate = null;
for (var i = 0; i < numbers.length; i++) {
if (numbers.indexOf(numbers[i]) !== i) {
duplicate = numbers[i];
break; // stop cycle
}
}
console.log(duplicate);
var numbers = [7, 5, 7, 6, 6, 4, 9, 10, 2, 11];
var map = {};
for (var i = 0; i < numbers.length; i++) {
if (map[numbers[i]] !== undefined) {
console.log(map[numbers[i]]);
break;
} else {
map[numbers[i]] = i;
}
}
Okay so let's break this down. What we're doing here is creating a map of numbers to the index at which they first occur. So as we loop through the array of numbers, we check to see if it's in our map of numbers. If it is we've found it and return the value at that key in our map. Otherwise we add the number as a key in our map which points to the index at which it first occurred. The reason we use a map is that it is really fast O(1) so our overall runtime is O(n), which is the fastest you can do this on an unsorted array.
As an alternative, you can use indexOf and lastIndexOf and if values are different, there are multiple repetition and you can break the loop;
function getFirstDuplicate(arr) {
for (var i = 0; i < arr.length; i++) {
if (arr.indexOf(arr[i]) !== arr.lastIndexOf(arr[i]))
return arr[i];
}
}
var arrWithNumbers = [2, 5, 5, 2, 3, 5, 1, 2, 4];
console.log(getFirstDuplicate(arrWithNumbers))
var numbers = [1, 3, 6, 7, 5, 7, 6, 6, 4, 9, 10, 2, 11]
console.log(getFirstDuplicate(numbers))
I have the same task and came up with this, pretty basic solution:
var arr = [7,4,2,4,5,1,6,8,9,4];
var firstIndex = 0;
for(var i = 0; i < arr.length; i++){
for( var j = i+1; j < arr.length; j++){
if(arr[i] == arr[j]){
firstIndex = arr[i];
break;
}
}
}
console.log(firstIndex);
First for loop takes the first element from array (number 7), then the other for loop checks all other elements against it, and so on.
Important here is to define j in second loop as i+1, if not, any element would find it's equal number at the same index and firstIndex would get the value of the last one after all loops are done.
To reduce the time complexity in the aforementioned answers you can go with this solution:
function getFirstRecurringNumber(arrayOfNumbers) {
const hashMap = new Map();
for (let number of arrayOfNumbers) { // Time complexity: O(n)
const numberDuplicatesCount = hashMap.get(number);
if (numberDuplicatesCount) {
hashMap.set(number, numberDuplicatesCount + 1);
continue;
}
hashMap.set(number, 1); // Space complexity: O(n)
}
for (let entry of hashMap.entries()) { // Time complexity: O(i)
if (entry[1] > 1) {
return entry[0];
}
}
}
// Time complexity: O(n + i) instead of O(n^2)
// Space complexity: O(n)
Using the code below, I am able to get just the first '5' that appears in the array. the .some() method stops looping through once it finds a match.
let james = [5, 1, 5, 8, 2, 7, 5, 8, 3, 5];
let onlyOneFives = [];
james.some(item => {
//checking for a condition.
if(james.indexOf(item) === 0) {
//if the condition is met, then it pushes the item to a new array and then
//returns true which stop the loop
onlyOneFives.push(item);
return james.indexOf(item) === 0;
}
})
console.log(onlyOneFives)
Create a function that takes an array with numbers, inside it do the following:
First, instantiate an empty object.
Secondly, make a for loop that iterates trough every element of the array and for each one, add them to the empty object and check if the length of the object has changed, if not, well that means that you added a element that already existed so you can return it:
//Return first recurring number of given array, if there isn't return undefined.
const firstRecurringNumberOf = array =>{
objectOfArray = {};
for (let dynamicIndex = 0; dynamicIndex < array.length; dynamicIndex ++) {
const elementsBeforeAdding = (Object.keys(objectOfArray)).length;0
objectOfArray[array[dynamicIndex]] = array[dynamicIndex]
const elementsAfterAdding = (Object.keys(objectOfArray)).length;
if(elementsBeforeAdding == elementsAfterAdding){ //it means that the element already existed in the object, so it didnt was added & length doesnt change.
return array[dynamicIndex];
}
}
return undefined;
}
console.log(firstRecurringNumberOf([1,2,3,4])); //returns undefined
console.log(firstRecurringNumberOf([1,4,3,4,2,3])); //returns 4
const arr = [1,9,5,2,3,0,0];
const copiedArray = [...arr];
const index = arr.findIndex((element,i) => {
copiedArray.splice(0,1);
return copiedArray.includes(element)
})
console.log(index);
var addIndex = [7, 5, 2, 3, 4, 5, 7,6, 2];
var firstmatch = [];
for (var i = 0; i < addIndex.length; i++) {
if ($.inArray(addIndex[i], firstmatch) > -1) {
return false;
}
firstmatch.push(addIndex[i]);
}

Finding largest integer in an array in JavaScript [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How might I find the largest number contained in a JavaScript array?
I am having trouble getting this code to work. I have been at it for a while trying to figure it out. When I look at the console it just displays 0. What did I do wrong?
Here is my code:
var array = [3 , 6, 2, 56, 32, 5, 89, 32];
var largest= 0;
for (i=0; i<=largest;i++){
if (array>largest) {
var largest=array[i];
}
}
console.log(largest);
var arr = [3, 6, 2, 56, 32, 5, 89, 32];
var largest = arr[0];
for (var i = 0; i < arr.length; i++) {
if (largest < arr[i] ) {
largest = arr[i];
}
}
console.log(largest);
You need to define i or else it become a global variable.
Don't redefine largest in the loop.
Since you're looping through the array, use i < array.length instead of i <= largest.
Since you're comparing each of the items in the array to largest, use if(largest < array[i]) instead of if(array > largest)
You should set largest equal to the first element in the array because what if all the numbers are negative?
array is a bad variable name because it's too similar to Array (the array constructor). Try arr instead.
One liner:
var largest = Math.max.apply(0, array);
More info here: Javascript max() function for 3 numbers
The code below is fixed and should work. The problem was that in this line if (array>largest) { You were not providing the index of the array. By changing the code to this if (array[i]>largest) { it works. Notice that I added the [i] to the end of array in the if statement.
var array = [3 , 6, 2, 56, 32, 5, 89, 32];
var largest= 0;
for (i=0; i<array.length; i++){
if (array[i]>largest) {
largest=array[i];
}
}
console.log(largest);
Just one line :)
var array = [3 , 6, 2, 56, 32, 5, 89, 32],
largest = array.sort((a,b)=>a-b).reverse()[0];
or even better
...
largest = array.sort((a,b)=>a-b)[array.length - 1];
UPD, all code above is sucks when you add for example 9 in array my guess because by default numbers treated as strings in sort, there is better version
var array = [3 , 6, 2, 56, 32, 5, 89, 32, 9], largest;
array.sort(function(a, b) {
largest = a > b ? a: b;
});
although in performance wise forEach loop suggested in comments are better
http://jsperf.com/array-sorting-javascript-stack
UPD2, okay, code above has some bad parts in it, so will not work as expected. Another try:
array.sort(function(a, b) {
return a - b;
});
largest = array[array.length - 1];
You have a few small mistakes. First:
if (array>largest) {
It should instead be:
if ( array[i]>largest) {
Second:
for ( i = 0; i <= largest; i++) {
should be
for (i = 0; i <= array.length; i++) {
var array = [3 , 6, 2, 56, 32, 5, 89, 32];
var largest= array[0];
for (i=0; i<=largest;i++){
if (array[i]>largest) {
largest=array[i];
}
}
You have two issues in your code. First, array>largest should be array[i]>largest. Second, you are declaring a new largest variable inside the if which isn't the same as the one outside. Remove var from the assignment of the new largest value.

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