JavaScript: Iterating through multi-dimensional arrays and extracting multiple search values - javascript

What I want to do:
Search through a multi-dimensional array using multiple search strings.
Example of what I am currently doing:
var multiArray = [['Apples and pears', 'tuna salad'],['bananas tuna'],['the colour blue']];
var singleArray = [];
var match_array = [];
// Turn multiple arrays into one big one
for (var i = 0; i < multiArray.length; i++) {
for (var x = 0; x < multiArray[i].length; x++) {
singleArray.push(multiArray[i][x]);
}
}
// Create a new array from matched strings
function find_match(to_match) {
for (var i in singleArray) {
if (singleArray[i].indexOf(to_match)!= -1)
match_array.push(singleArray[i]);
}
return (match_array.length === 0 ? null : match_array);
}
// Find matching terms for match_array
find_match('tuna');
find_match('the');
alert(match_array);
JSFiddle Demo
Questions:
Obviously this is a cluttered way of doing this. How can this be
streamlined(i.e. searching the multiArray directly and not using
multiple find_match functions)?
How can I get only the exact string matches, preferably without breaking up the multi-dimensional array?
What are your thoughts about searching through massive
multidimensional arrays?

Do you want something like this?
var multiArray = [['Foo', 'Bar'],['Foo'],['Bar']];
var singleArray = [];
var match_array = [];
// Turn multiple arrays into one big one
for (var i = 0; i < multiArray.length; i++) {
for (var x = 0; x < multiArray[i].length; x++) {
singleArray.push(multiArray[i][x]);
}
}
// Create a new array from matched strings
function find_match(to_match, where_search) {
for (var j in where_search) {
if(where_search[j] instanceof Array){
find_match(to_match, where_search[j]);
}else{
for (var i in to_match) {
if (where_search[j].indexOf(to_match[i]) ==0 &&
where_search[j].length == to_match[i].length)
match_array.push(where_search[j]);
}
}
}
return (where_search.length === 0 ? null : match_array);
}
// Find matching terms for match_array
find_match(['Foo', 'Bar'],multiArray);
alert(match_array);

Related

Two dimensional arrays populating does not work javascript

When i try to create two dimensional array in javascript using loop, it gives me following error:
Cannot set property 'indexis' of undefined
Code:
var indexes = [];
for (var i = 0; i < headingsArray.length; i++) {
if (headingsArray[i].toLowerCase().indexOf('name') != -1) {
indexes[i]['indexis'] = i;
indexes[i]['headingis'] = headingsArray[i]; //assuming headingsArray exist
indexes[i]['valueis'] = rows[0][i]; //assuming rows exist
}
}
You need to create the inner arrays/objects as well, or else index[i] is undefined, so index[i]['indexis'] will throw an exception.
var indexes = [];
for (var i = 0; i < headingsArray.length; i++) {
indexes[i] = {}; //<---- need this
if (headingsArray[i].toLowerCase().indexOf('name') != -1) {
indexes[i]['indexis'] = i;
indexes[i]['headingis'] = headingsArray[i];
indexes[i]['valueis'] = rows[0][i];
}
}
You described it as a multidimensional array, but you're using it as though it's an array of objects (because you're accessing named properties, instead of numbered properties). So my example code is creating objects on each iteration. If you meant to have an array of arrays, then do indexes[i] = [], and interact with things like indexes[i][0] rather than indexes[i]['indexis']
You need an object before accessing a property of it.
indexes[i] = indexes[i] || {}
indexes[i]['indexis'] = i;
define temp var with field initialise to null & use push() function of JavaScript
for (var i = 0; i < headingsArray.length; i++) {
var temp={indexis: null,headingis:null,valueis:null};;
if (headingsArray) {
temp['indexis'] = i;
temp['headingis'] = headingsArray[i]; //assuming headingsArray exist
temp['valueis'] = rows[0][i];
indexes.push(temp);
}
}

Fastest way to join two Javascript/JSON Objects by ID

Assuming I have two Javascript Objects (they have a JSON structure, but are created with JSON.parse()). All entries have a unique ID with which the entries from both objects can be matched.
What would be the fastest way to join both objects (native javascript).
The first thing that comes into my mind would be a nested for in loop.
for(var i in firstJson) {
for(var j in secondJson) {
if(firstJson[i].id === secondJson[j].id) {
// join them
}
}
}
Is there a faster way?
More efficient way would be to create an index out of one of them:
var index = {};
for (var j in secondJson) {
var obj = secondJson[j];
index[obj.id] = obj;
};
for (var i in firstJson) {
var firstObj = firstJson[i];
var match = index[firstObj.id];
if (match) {
// do the stuff
}
};
This is O(n+m) instead of O(n*m) for nested loops. At the cost of O(m) memory of course.
If both lists are not already sorted you could first sort them by id, then do the comparison and saving the position of the last found object, starting from the last found if nothing was found.
(I do believe that the solution from freakish is faster, but this has no extra memory consumption)
This should be on the order O(nlog(n)+mlog(m)+m)
first.Sort();
second.Sort();
int idx = 0;
int lastIdx = 0;
for (int i = 0; i < first.Count; i++) {
for (int j = idx; j < second.Count; j++)
{
if (first[i] == second[j])
{
Console.WriteLine("equal " + first[i]);
idx = j + 1;
lastIdx = idx;
break;
}
}
if (idx == second.Count)
idx = lastIdx;
}

Inserting items into a 2D array

I am working on solving an algorithm (do not want to explain my approach, as I am still trying to solve it on my own). However I am having difficulty with a particular part.
function smallestCommons(arr)
{
var rangeArray = [];
var outterArray = [];
var testArray = [];
arr = arr.sort(function(a,b){return a>b});
for(var i=arr[0];i<=arr[1];i++)
{
rangeArray.push(i);
}
for(var j=0;j<rangeArray.length;j++)
{
for(var k=1;k<=100;k++)
{
if(k%rangeArray[j] === 0)
{
outterArray.push([k]);
}
}
}
console.log(outterArray);
}
smallestCommons([1,5]);
The second part of the code I am looping through the items in rangeArray [1,2,3,4,5] and trying to insert all the multiples (from 1 to 100) of EACH index into a DIFFERENT array. But my code currently is pushing EACH individual number which is a multiple into its own array per each digit. I need it to push all the multiples of each index of rangeArray into outer array. So that I end up with a 2D array of all the multiples of rangeArray in different array for every iteration of j.
So for example instead of ending up with
outerArray == [[1],[2],[3]...]
I would end up with all the multiples of 1 (up to 100) into one array and then all the multiples of 2 into another array and so on and so forth so it looks like this.
outerArray == [[1,2,3,4...] [2,4,6,8...] [3,6,9,12...]]
Its very hard to explain, hopefully I have been clear. Thanks.
It's quite impossible to understand your question, but wisely you've described the output you're trying to generate...
Turns out, that's quite simple:
let arr = [];
for(let i = 1; i <= 100; i++) {
let innerArr = [];
for(let j = i; j <= 100; j += i) {
innerArr.push(j);
}
arr.push(innerArr);
}
console.log(arr);
how many elements should be in each multiple array? I guessed 100 but you can adjust that accordingly...
function smallestCommons(arr)
{
var rangeArray = [];
var outterArray = [];
var testArray = [];
arr = arr.sort(function(a,b){return a>b});
for(var i=arr[0];i<=arr[1];i++)
{
rangeArray.push(i);
}
for(var j=0;j<rangeArray.length;j++)
{
for(var k=1;k<=100;k++)
{
if(k%rangeArray[j] === 0)
{
var multipleArray = [];
for(var z=1;z<100;z++) {
multipleArray.push(z*k);
}
outterArray.push(multipleArray);
}
}
}
console.log(outterArray);
}
smallestCommons([1,5]);

Using two separate objects, I would like to return an object with the matching key, value pairs?

I have created three functions, that can make two separate arrays with the matching keys and the matching properties. I would like to use those two arrays to create a new object with all of the matching pairs. Below I included the functions I have so far.
I am a beginner in Javascript ( which is most likely already apparent) so if you can explain each step thoroughly and not get to complex I would greatly appreciate it.
function contains(array, obj_to_check){
for(var i = 0; i < array.length; i ++) {
if (array[i] == obj_to_check) {
return true;
}
}
}
function sharedKeys(obj1, obj2) {
var obj1Keys = Object.keys(obj1);
var obj2Keys = Object.keys(obj2);
var sharedArray = [];
for( var x = 0; x < obj1Keys.length; x++){
if (contains(obj2Keys, obj1Keys[x])){
sharedArray.push(obj1Keys[x]);
}
}
return sharedArray;
}
function sharedProperties(obj1, obj2) {
var obj1Props = [];
var obj2Props = [];
var propertiesArray = [];
for(var i in obj1)
obj1Props.push(obj1[i]);
for(var x in obj2)
obj2Props.push(obj2[x]);
for (var y = 0; y < obj1Props.length; y ++){
if(contains(obj1Props, obj2Props[y])){
propertiesArray.push(obj2Props[y])
}
}
return propertiesArray;
}
You are comparing two objects, not two values. The only way that your == comparison works here is if both of them refer to the same object. You need to check and see if every properties and fields of those two objects are equal. Besides, check this thread about comparison in JavaScript.

Remove duplicate element pairs from multidimensional array

I have an array that looks like this:
1. coordinates = [ [16.343345, 35.123523],
2. [14.325423, 34.632723],
3. [15.231512, 35.426914],
4. [16.343345, 35.123523],
5. [15.231512, 32.426914] ]
The latitude on line 5 is the same as on line 3, but they have different longitudes and are therefore not duplicates.
Both the latitude and longitude are the same on line 3 and 6, and are therefore duplicates and one should be removed.
The difficulty in this question that different arrays never compare equal even if they contain same values. Therefore direct comparison methods, like indexOf won't work.
The following pattern might be useful to solve this. Write a function (or use a built-in one) that converts arrays to scalar values and checks if these values are unique in a set.
uniq = function(items, key) {
var set = {};
return items.filter(function(item) {
var k = key ? key.apply(item) : item;
return k in set ? false : set[k] = true;
})
}
where key is a "hash" function that convert items (whatever they are) to comparable scalar values. In your particular example, it seems to be enough just to apply Array.join to arrays:
uniqueCoords = uniq(coordinates, [].join)
You can use standard javascript function splice for this.
for(var i = 0; i < coordinates.length; i++) {
for(var j = i + 1; j < coordinates.length; ) {
if(coordinates[i][0] == coordinates[j][0] && coordinates[i][1] == coordinates[j][1])
// Found the same. Remove it.
coordinates.splice(j, 1);
else
// No match. Go ahead.
j++;
}
}
However, if you have thousands of points it will work slowly, than you need to consider to sort values at first, then remove duplicates in one loop.
I rewrote the answer from thg435 (It does not allow me to post comments) and prototype it also using jQuery instead, so this will work on all browsers using it (Even IE7)
Array.prototype.uniq = function (key) {
var set = {};
return $.grep(this, function (item) {
var k = key
? key.apply(item)
: item;
return k in set
? false
: set[k] = true;
});
}
You can use it like:
arr = arr.uniq([].join);
If you are not on Safari this single liner could do the job
var arr = [[16.343345, 35.123523],
[14.325423, 34.632723],
[15.231512, 35.426914],
[16.343345, 35.123523],
[15.231512, 32.426914]],
lut = {},
red = arr.filter(a => lut[a] ? false : lut[a] = true);
document.write("<pre>" + JSON.stringify(red,null,2) + "</pre>");
It might be simpler to create another array keeping only unique coordinate pairs
var uniqueCoors = [];
var doneCoors = [];
for(var x = 0; x < coordinates.length; x++) {
var coorStr = coordinates[x].toString();
if(doneCoors.indexOf(coorStr) != -1) {
// coordinate already exist, ignore
continue;
}
doneCoors.push(coorStr);
uniqueCoors.push(coordinates[x]);
}
function sortCoordinates(arr){
var obj = {};
for(var i = 0, l = arr.length; i < l; i++){
var el = arr[i];
var lat = el[0];
var lng = el[1];
if(!obj[lat + lng]){
obj[lat + lng] = [lat, lng];
}
}
var out = [];
for(p in obj){
out.push([obj[p][0], obj[p][1]]);
}
return out;
}
I am not sure about coordinates[][] dataType. Make the comparison accordingly.
var dubJRows= new Array();
for(int i = 0; i < coordinates.length -2; i++){
for(int j = i+1; j < coordinates.length -1; j++){
if (i != j && chk_dubJRows_not_contains(j)) {
innerArray1 [1][1] = coordinates[i];
innerArray2 [1][1] = coordinates[j];
if ( innerArray1 [1][0] == innerArray2[1][0]
&& innerArray1[1][1] == innerArray2[1][1]) {
dubJRows.push(j);
}
}
}
}
//REMOVE ALL dubJRows from coordinates.

Categories