Find the index of a sub array that contains a number - javascript

var array = [[2,3,4],[4,5,6],[2,3,9]];
var number = 9;
If I have this nested array and this variable how do I return the index
where the sub-array with the number is. So the final result should be 2 or.
So far I have:
var indexOfRemainingArray = array.filter(function(item,i) {
if(item != number) {
return i;
}
});
I would like to know how to use map or filter functions for this.

Use Array#findIndex to find the index, and use Array#indexOf in the callback to check if the sub array contains the number at least once.
var array = [[2,3,4],[4,5,6],[2,3,9]];
var number = 9;
var indexOfRemainingArray = array.findIndex(function(sub) {
return sub.indexOf(number) !== -1;
});
console.log(indexOfRemainingArray);
And if you need both indexes, you can assign the result of the inner indexOf to a variable:
var array = [[2,3,4],[4,5,9],[2,3,1]];
var number = 9;
var innerIndex;
var indexOfRemainingArray = array.findIndex(function(sub) {
innerIndex = sub.indexOf(number);
return innerIndex !== -1;
});
console.log(indexOfRemainingArray, innerIndex);

Related

Javascript | Why does the variable equal undefined?

In this code largestGap is equal to undefined when it is logged. Basically this code is turning the string of 1s and 0s into an array and finding the largest gap between two 1s, as you can see looking through largestGap should equal 4, but as stated earlier it returns undefined.
var gaps = [];
var gapCount = 0;
var largestGap = gaps[0];
var string = '10010001000010001001';
string.split('');
var stringArray = Array.from(string);
stringArray.forEach(function(item, array) {
if (item == '1') {
if (gapCount > 0) {
gaps.push(gapCount);
}
gapCount = 0;
} else {
gapCount++;
}
});
for (i = 0; i < gaps.length; i++) {
if (largestGap < gaps[i]) {
largestGap = arr[i];
}
}
console.log(`The largest gap in the string is ${largestGap}`);
You initialize largestGap like:
var largestGap = gaps[0];
But the gaps array is empty initially. Initialize it only after the gaps array is populated, otherwise the test later (if (largestGap < gaps[i])) will not work.
There's also no arr variable. Use the gaps variable instead:
var gaps = [];
var gapCount = 0;
var string = '10010001000010001001';
var stringArray = Array.from(string);
stringArray.forEach(function(item, array) {
if (item == '1') {
if (gapCount > 0) {
gaps.push(gapCount);
}
gapCount = 0;
} else {
gapCount++;
}
});
var largestGap = 0;
for (i = 0; i < gaps.length; i++) {
if (largestGap < gaps[i]) {
largestGap = gaps[i];
}
}
console.log(`The largest gap in the string is ${largestGap}`);
Note that string.split(''); does nothing - it creates an array, and that array is never used, so you can remove that line.
This could be done much more concisely by matching 0s with a regular expression, then mapping the array of matched substrings to each match's length, then calling Math.max with that array of lengths:
const string = '10010001000010001001';
const matchLengths = (string.match(/0+/g) || []).map(str => str.length);
const largestGap = Math.max(...matchLengths);
console.log(`The largest gap in the string is ${largestGap}`);
The || [] is needed because, if there are no matches, the global regular expression match will return null rather than an empty array. If you're sure there will be at least one 0 in the string, you can remove that part to simplify things.
You are getting value from an empty array thats why first you should fill the gap array the use gap[0] insead of doing it before you even pushed anything to the array
you are assigning variables as
var gaps = [];
var gapCount = 0;
var largestGap = gaps[0];
So largestGap in the end also will have no value as it is assigned at the beginning when gaps variable had no value

Find common objects in multiple arrays by object ID

I've searched SO for a way to do this but most questions only support two arrays (I need a solution for multiple arrays).
I don't want to compare exact objects, I want to compare objects by their ID, as their other parameters may differ.
So here's the example data:
data1 = [{'id':'13','name':'sophie'},{'id':'22','name':'andrew'}, etc.]
data2 = [{'id':'22','name':'mary'},{'id':'85','name':'bill'}, etc.]
data3 = [{'id':'20','name':'steve'},{'id':'22','name':'john'}, etc.]
...
I'd like to return all objects whose ID appears in all arrays, and I don't mind which of the set of matched objects is returned.
So, from the data above, I'd expect to return any one of the following:
{'id':'22','name':'andrew'}
{'id':'22','name':'mary'}
{'id':'22','name':'john'}
Thanks
First, you really need an array of arrays - using a numeric suffix is not extensible:
let data = [ data1, data2, ... ];
Since you've confirmed that the IDs are unique within each sub array, you can simplify the problem by merging the arrays, and then finding out which elements occur n times, where n is the original number of sub arrays:
let flattened = data.reduce((a, b) => a.concat(b), []);
let counts = flattened.reduce(
(map, { id }) => map.set(id, (map.get(id) || 0) + 1), new Map()
);
and then you can pick out those objects that did appear n times, in this simple version they'll all come from the first sub array:
let found = data[0].filter(({ id }) => counts.get(id) === data.length);
Picking an arbitrary (unique) match from each sub array would be somewhat difficult, although picking just one row of data and picking the items from that would be relatively easy. Either would satisfy the constraint from the question.
If you want the unique object by Name
data1 = [{'id':'13','name':'sophie'},{'id':'22','name':'mary'}]
data2 = [{'id':'26','name':'mary'},{'id':'85','name':'bill'}]
data3 = [{'id':'29','name':'sophie'},{'id':'22','name':'john'}]
flattened = [ ...data1, ...data2, ...data3 ];
counts = flattened.reduce(
(map, { name }) => map.set(name, (map.get(name) || 0) + 1), new Map()
);
names = []
found = flattened.filter(({ name }) => {
if ((counts.get(name) > 1) && (!names.includes(name))) {
names.push(name);
return true
}
return false
});
its too many loops but , if u can find the common id which is present in all the arrays then it would make your finding easier i think .you can have one array value as reference to find the common id
var global = [];
for(var i = 0;i<data1.length;i++){
var presence = true;
for(var j=0;j<arrays.length;j++){
var temp = arrays[j].find(function(value){
return data1[i].id == value.id;
});
if(!temp){
presence = false;
break;
}
}
if(presence){
global.push(data1[i].id)
}
}
console.log(global);
var data1 = [{'id':'13','name':'sophie'},{'id':'22','name':'andrew'}];
var data2 = [{'id':'22','name':'mary'},{'id':'85','name':'bill'}];
var data3 = [{'id':'20','name':'steve'},{'id':'22','name':'john'}];
var arrays = [data1, data2, data3];
var global = [];
for(var i = 0;i<data1.length;i++){
var presence = true;
for(var j=0;j<arrays.length;j++){
var temp = arrays[j].find(function(value){
return data1[i].id == value.id;
});
if(!temp){
presence = false;
break;
}
}
if(presence){
global.push(data1[i].id)
}
}
console.log(global);
There's mention you you need n arrays, but also, given that you can:
put all the arrays into an array called data
you can:
combine your arrays
get a list of duplicated IDs (via sort by ID)
make that list unique (unique list of IDs)
find entries in the combined list that match the unique IDs
where the count of those items match the original number of arrays
Sample code:
// Original data
var data1 = [{'id':'13','name':'sophie'},{'id':'22','name':'andrew'}]
var data2 = [{'id':'22','name':'mary'},{'id':'85','name':'bill'}]
var data3 = [{'id':'13','name':'steve'},{'id':'22','name':'john'}]
var arraycount = 3;
// Combine data into a single array
// This might be done by .pushing to an array of arrays and then using .length
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort?v=control
var data = [].concat(data1).concat(data2).concat(data3);
//console.log(data)
// Sort array by ID
// http://stackoverflow.com/questions/840781/easiest-way-to-find-duplicate-values-in-a-javascript-array
var sorted_arr = data.slice().sort(function(a, b) {
return a.id - b.id;
});
//console.log(sorted_arr)
// Find duplicate IDs
var duplicate_arr = [];
for (var i = 0; i < data.length - 1; i++) {
if (sorted_arr[i + 1].id == sorted_arr[i].id) {
duplicate_arr.push(sorted_arr[i].id);
}
}
// Find unique IDs
// http://stackoverflow.com/questions/1960473/unique-values-in-an-array
var unique = duplicate_arr.filter(function(value, index, self) {
return self.indexOf(value) === index;
});
//console.log(unique);
// Get values back from data
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter?v=control
var matches = [];
for (var i = 0; i < unique.length; ++i) {
var id = unique[i];
matches.push(data.filter(function(e) {
return e.id == id;
}))
}
//console.log(matches)
// for data set this will be 13 and 22
// Where they match all the arrays
var result = matches.filter(function(value, index, self) {
return value.length == arraycount;
})
//console.log("Result:")
console.log(result)
Note: There's very likely to be more efficient methods.. I've left this in the hope part of it might help someone
var arr1 = ["558", "s1", "10"];
var arr2 = ["55", "s1", "103"];
var arr3 = ["55", "s1", "104"];
var arr = [arr1, arr2, arr3];
console.log(arr.reduce((p, c) => p.filter(e => c.includes(e))));
// output ["s1"]

Javascript Searching Array for partial string

Have a function that returns an array of objects. The array has a rate object that has a name field. Inside the name field are names such as "Slow speed" and "Fast speed".
I have written the following in hopes to create a new array that will filter out the array values and just return only those with "Slow" that matches from the rates[i].name.
So far I am encountering this error in my dev console.
"Uncaught TypeError: value.substring is not a function"
var rates = myArray();
var index, value, result;
var newArr = [];
for (index = 0; index < rates.length; ++index) {
//value = rates[index];
if (value.substring(0, 5) === "Stand") {
result = value;
newArr.push();
break;
}
}
Part of array return in console.
"rates":[{"id":1123,"price":"1.99","name":"Slow speed - Red Car","policy":{"durqty":1,"durtype":"D","spdup":15000,"spddwn":15000}
You have an object at each array location not the string itself, try this instead:
var rates = myArray();
var index, value, result;
var newArr = [];
for (index = 0; index < rates.length; ++index) {
name = rates[index].name;
if (name.substring(0, 4) === "Slow") {
newArr.push(rates[index]);
}
}
Try using filter function like this, it is much more cleaner to see
var newArr = rates.filter(function(rate){
return rate.name && rate.name.substring(0,4) === "Slow";
});
You can use filter to do this, for example:
var newArr = rates.filter(function(val){
// check if this object has a property `name` and this property's value starts with `Slow`.
return val.name && val.name.indexOf("Slow") == 0;
});
As #4castle mentioned, instead of indexOf(...) you can use slice(...) which may be more efficent, eg: val.name.slice(0,4) == "Slow"

Remove data from an array comparing it to an other array

I am trying to compare the items in "item" array and the copyofOpList array to retrieve the data occurrences in copyofOpList
this is my try:
var _deleteUsedElement1 = function(item) {
for (var i = 0; i < item.length-1; i++){
for (var j = 0; j< $scope.copyofOpList.length-1; j++){
if (item[i].operationCode == $scope.copyofOpList[j].code) {
$scope.copyofOpList.splice(j, 1);
} } } };
$scope.compareArrays = function() {
...Get data from web Service
_deleteUsedElement1(item);
}
the copyofOpList array has 14 elements,and the item array has 2 array
but my code deletes only one occurrence (the first),so please how can I correct my code,to retrieve any occurances in the copyofOpList array comparing to the item array
thanks for help
I'd try to avoid looping inside a loop - that's neither a very elegant nor a very efficient way to get the result you want.
Here's something more elegant and most likely more efficient:
var item = [1,2], copyofOpList = [1,2,3,4,5,6,7];
var _deleteUsedElement1 = function(item, copyofOpList) {
return copyofOpList.filter(function(listItem) {
return item.indexOf(listItem) === -1;
});
};
copyofOpList = _deleteUsedElement1(item, copyofOpList);
console.log(copyofOpList);
//prints [3,4,5,6,7]
}
And since I just noticed that you're comparing object properties, here's a version that filters on matching object properties:
var item = [{opCode:1},{opCode:2}],
copyofOpList = [{opCode:1},{opCode:2},{opCode:3},{opCode:4},{opCode:5},{opCode:6},{opCode:7}];
var _deleteUsedElement1 = function(item, copyofOpList) {
var iOpCodes = item.map(function (i) {return i.opCode;});
return copyofOpList.filter(function(listItem) {
return iOpCodes.indexOf(listItem.opCode) === -1;
});
};
copyofOpList = _deleteUsedElement1(item, copyofOpList);
console.log(copyofOpList);
//prints [{opCode:3},{opCode:4},{opCode:5},{opCode:6},{opCode:7}]
Another benefit of doing it in this manner is that you avoid modifying your arrays while you're still operating on them, a positive effect that both JonSG and Furhan S. mentioned in their answers.
Splicing will change your array. Use a temporary buffer array for new values like this:
var _deleteUsedElement1 = function(item) {
var _temp = [];
for (var i = 0; i < $scope.copyofOpList.length-1; i++){
for (var j = 0; j< item.length-1; j++){
if ($scope.copyofOpList[i].code != item[j].operationCode) {
_temp.push($scope.copyofOpList[j]);
}
}
}
$scope.copyofOpList = _temp;
};

Get full value from array using partial value

I have an array like this:
var array = ["xs-1", "sm-10", "md-4"];
Now I want to get the number at the end of a particular value. For example I want to search the array for "md-" and see what number is at the end of that string (should return 4).
I can't do array.indexOf("xs-") because that isn't the whole value. Is there a way to do this?
Using a for loop:
var array = ["xs-1", "sm-10", "md-4"];
var search = "md-";
var found = null;
for (var i = 0; i < array.length; i++) {
if (array[i].indexOf(search) === 0) {
found = array[i];
break; // Note: this is assuming only one match exists - or at least you are
// only interested in the first match
}
}
if (found) {
alert(found);
} else {
alert("Not found");
}
Using .filter:
var array = ["xs-1", "sm-10", "md-4"];
var search = "md-";
var filtered = array.filter(function(item) {
return item.indexOf(search) === 0;
});
// note that here filtered will contain all matched elements, so it might be more than
// one match.
alert(filtered);
Building from #János Weisz's suggestion, you can easily transform your array into an object using .reduce:
var array = ["xs-1", "sm-10", "md-4"];
var search = "md";
var obj = array.reduce(function(prev, item) {
var cells = item.split("-");
prev[cells[0]] = cells[1];
return prev;
}, {});
// note: at this point we have an object that looks like this:
// { xs:1, sm:10, md: 4 }
// if we save this object, we can do lookups much faster than looping
// through an array
// now to find "md", we simply do:
alert(obj[search]);
If you need to do multiple look ups from the same source array, then transforming it into an object may be the most efficient approach overall. You pay the initial price of the transformation, but after than lookups are O(1) versus O(n) for each time you have to search your array. Of course, if you only ever need one item, then probably don't bother.
I recommend using objects for this:
var array = [{'type': 'xs', 'value': 1}, {'type' : 'sm', 'value': '10'}, {'type' : 'md', 'value': '4'}];
This way you can search the array as:
function searchMyArrayByType(array, type) {
var items[];
for (var i = 0; i < array.length; i++)
{
if (array[i].type == type) items.push(array[i].value);
}
return items;
}
var valuesWithMd = searchMyArrayByType(array, 'md');
For more information regarding the structure and use of objects, please refer to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects
You can create a method that takes the prefix you're looking for, the array, and the split character and returns all the numbers in an array:
function findNumberFromPrefix(prefix, arr, splitChar) {
var values = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i].indexOf(prefix) === 0) {
values.push(arr[i].split(splitChar)[1]);
}
}
return values;
}
And call it:
var array = ["xs-1", "sm-10", "md-4"];
var values = findNumberFromPrefix("md-", array, "-");
console.log(values); //["4"]
Demo: http://jsfiddle.net/rn4h9msh/
A more functional approach and assuming you can have have more than one element with the same prefix:
function findPrefix(array, prefix) {
return array.filter(function (a) { return a.indexOf(prefix) === 0; })
.map(function (e) { return e.slice(prefix.length); })
}
If you have only one matching element, do a loop like this:
var array = ["xs-1", "sm-10", "md-4"];
var needle = "md-";
for(i=0;i<array.length;i++) {
if(array[i].indexOf(needle) == 0)
alert(array[i].substr(needle.length, array[i].length));
}
Demo: http://jsfiddle.net/kg0c43ov/
You can do it like this...
var array = ["xs-1", "sm-10", "md-4"];
getValue("md-");
function getValue(search) {
for(var key in array) {
if(array[key].indexOf(search) > -1) {
alert("Array key is: " + key);
alert("Array value is: " + array[key].replace(search, ""));
}
}
}
JSFiddle here.

Categories

Resources