Related
I'm pretty new in js, I have an array that looks like this:
[ 'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,on',
'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,off',
'com--fxtrimester,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,on'
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,off',
'com--fxyear,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxyear,SEzlksdfMpksfhksfMmqkPczCl2,off' ]
How can I delete the rows from the array that has:
-> the last value "off" AND the first two values the same as a line with the "on" value
like this:
(*) [ 'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,on',
'com--fxtrimester,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,on',
'com--fxyear,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxyear,SEzlksdfMpksfhksfMmqkPczCl2,off' ]
So I was like:
var productIds = [];
var userIds = [];
var status = [];
unique.forEach(function(data) {
var dataArray = data.split(',');
productIds.push(dataArray[0]);
userIds.push(dataArray[1]);
status.push(dataArray[2]);
});
for (var h = 0; userIds.length >= h; h++) {
if (status[h] == "on") {
for (var k = 0; userIds.length >= k; k++) {
if (status[k] == "off" &&
userIds[h] == userIds[k] &&
productIds[h] == productIds[k]) {
delete status[k];
delete userIds[k];
delete productIds[k];
}
}
}
}
But I think it is so much code... and well, just the forEach is the one working fine (separating into three objects) And the for loops I think work wrong because forEach is async. So is there any way I could improve the code to get that output mentioned (*)?
After this I need to send the array with the off rows that were left.
You can use Array filter.
Here an example:
var array = ['com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,on', 'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,off', 'com--fxtrimester,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on', 'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,on', 'com-fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,off', 'com--fxyear,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on'];
function checkFilter(str) {
return str.indexOf('off') !== str.length - 3 || str.indexOf('co') !== 0;
}
function myFunction() {
document.getElementById("demo").innerHTML = array.filter(checkFilter);
}
You can test this code here http://www.w3schools.com/code/tryit.asp?filename=FBN71QBHVUS1
The doc http://www.w3schools.com/jsref/jsref_filter.asp
var data = ['com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,on',
'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,off',
'com--fxtrimester,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,on',
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,off',
'com--fxyear,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxyear,SEzlksdfMpksfhksfMmqkPczCl2,off'
];
// es6
// var output = data.filter(d => !(d.endsWith('off') && data.find(val => val.endsWith('on') && val.startsWith(d.substr(0, d.length - 3)))));
// es5
var output = data.filter(function(d) {
return !(d.indexOf('off') === d.length - 3 && data.filter(function(val) {
return val.indexOf('on') === val.length - 2 && val.indexOf(d.substr(0, d.length - 3)) === 0
}).length);
});
console.log(output);
If your array is not too long (if the efficiency is not so critical) then you can hack the .sort() function of the Array and get your desired output.
var arr = [ 'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,on',
'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,off',
'com--fxtrimester,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,on',
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,off',
'com--fxyear,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxyear,SEzlksdfMpksfhksfMmqkPczCl2,off' ];
var removeOffOrOnFromStr = function(str){
return str.split(",", 2).toString()
}
var removeOffFromArray = function(arr, first, second){
var off = first;
if(second[second.length - 1] == "f"){
off = second;
}
arr.splice(arr.indexOf(off), 1)
}
var filtered = arr.slice()
arr.sort(function(first, second){
var removedOnOrOff1 = removeOffOrOnFromStr(first)
var removedOnOrOff2 = removeOffOrOnFromStr(second)
var thirdValueDiff = false
if(first[first.length - 1] != second[second.length - 1]){
thirdValueDiff = true
}
if(removedOnOrOff1 == removedOnOrOff2 && thirdValueDiff ){
removeOffFromArray(filtered, first, second)
}
});
console.log(filtered)
You may use Array.filter() method.
Please find details here
MDN Array filter method.
edit: I did miss your second requirement, now fixed, still using filter plus a (very) small bit of regex:
var target = [ 'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,on', 'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,off', 'com--fxtrimester,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,on', 'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,off', 'com--fxyear,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxyear,SEzlksdfMpksfhksfMmqkPczCl2,off' ];
var withOn = target.filter(function(el){return /on$/.test(el)});
var filteredResult = target.filter(
function(el){
var valueToMatch= el.match(/.*(?=,)/);//everything up to last comma
return !(/off$/.test(el) && withOn.filter(function(el){ return el.match(valueToMatch);}).length>0);//check for ending with 'off' and that one of the 'ons' has the same value
});
console.log(filteredResult);
Python startswith() allows me to test if a string starts with a tuple of strings as shown below, which is what I want to achieve with JavaScript:
testvar = 'he', 'hi', 'no', 'ye'
if my_string.startswith(testvar):
return True
I have seen this SO question and it did not completely help in achieving this.
I need to have a JavaScript code that will do the same thing with the Python code above.
Since there has been many solutions for having an array passed as argument, I am gonna post a solution splat "*" style arguments:
String.prototype.startsWithSplat = function(){
var args = Array.prototype.slice.call(arguments, 0, arguments.length);
var i;
var matched = false;
var self = this;
for(i = 0; i < args.length; i++){
if(self.slice(0, args[i].length) == args[i]){
matched = true;
break;
}
}
return matched;
}
Then you can just call:
my_string.startswith('he', 'hi', 'no', 'ye');
All you need is a simple loop over an Array with one of the answers shown there,
var testvar = ['he', 'hi', 'no', 'ye'];
function startsWith2(haystack, needles) {
var i = needles.length;
while (i-- > 0)
if (haystack.lastIndexOf(needles[i], 0) === 0)
return true;
return false;
}
startsWith2('hello world', testvar); // true
startsWith2('foo bar baz', testvar); // false
Similarly for endsWith;
function endsWith2(haystack, needles) {
var i = needles.length, j, k = haystack.length;
while (i-- > 0) {
j = k - needles[i].length;
if (j >= 0 && haystack.indexOf(needles[i], j) === j)
return true;
}
return false;
}
Since they're all the same length you could just do:
testvar = ['he', 'hi', 'no', 'ye']
return testvar.indexOf(my_string.substring(0,2)) > -1
And some examples:
// Examples:
testvar = ['he', 'hi', 'no', 'ye']
my_string = 'hello'
testvar.indexOf(my_string.substring(0,2)) > -1
true
my_string = 'apples'
testvar.indexOf(my_string.substring(0,2)) > -1
false
You can run a reduce operation over your array of tests to find if a variable starts with any of them.
var testVar = ['he', 'hi', 'no', 'ye'];
var myString = 'hello';
var startsWithAny = testVar.reduce(function (returnValue, currentTest) {
return returnValue || myString.startsWith(currentTest);
});
if (startsWithAny) {
return true;
}
var testvar = ['he','hi','no','ye'];
var str = "hello";
for(i = 0; i < testvar.length; i++)
{
if (str.startsWith(testvar[i]) == true)
console.log(str+" starts with: "+testvar[i]);
}
Let's say we have the following js array
var ar = [
[2,6,89,45],
[3,566,23,79],
[434,677,9,23]
];
var val = [3,566,23,79];
Is there a js builtin function or jQuery one with which you can search the array ar for val?
Thanks
***UPDATE*************
Taking fusion's response I created this prototype
Array.prototype.containsArray = function(val) {
var hash = {};
for(var i=0; i<this.length; i++) {
hash[this[i]] = i;
}
return hash.hasOwnProperty(val);
}
you could create a hash.
var ar = [
[2,6,89,45],
[3,566,23,79],
[434,677,9,23]
];
var hash = {};
for(var i = 0 ; i < ar.length; i += 1) {
hash[ar[i]] = i;
}
var val = [434,677,9,23];
if(hash.hasOwnProperty(val)) {
document.write(hash[val]);
}
You can also use a trick with JSON serializing. It is short and simple, but kind of hacky.
It works, because "[0,1]" === "[0,1]".
Here is the working demo snippet:
Array.prototype.indexOfForArrays = function(search)
{
var searchJson = JSON.stringify(search); // "[3,566,23,79]"
var arrJson = this.map(JSON.stringify); // ["[2,6,89,45]", "[3,566,23,79]", "[434,677,9,23]"]
return arrJson.indexOf(searchJson);
};
var arr = [
[2,6,89,45],
[3,566,23,79],
[434,677,9,23]
];
document.body.innerText = arr.indexOfForArrays([3,566,23,79]);
function indexOfArray(val, array) {
var hash = {};
for (var i = 0; i < array.length; i++) {
hash[array[i]] = i;
}
return (hash.hasOwnProperty(val)) ? hash[val] : -1;
};
I consider this more useful for than containsArray(). It solves the same problem (using a hash table) but returns the index (rather than only boolean true/false).
Can you try this?
var ar = [
[2,6,89,45],
[3,566,23,79],
[434,677,9,23]
];
var val = [3,566,23,79];
var sval = val.join("");
for(var i in ar)
{
var sar = ar[i].join("");
if (sar==sval)
{
alert("found!");
break;
}
}
Why don't you use javascript array functions?
function filterArrayByValues(array, values) {
return array.filter(function (arrayItem) {
return values.some(function (value) {
return value === arrayItem;
});
});
}
Or if your array is more complicated, and you want compare only one property but as result return whole object:
function filterArrayByValues(array, values, propertyName) {
return array.filter(function (arrayItem) {
return values.some(function (value) {
return value === arrayItem[propertyName];
});
});
}
More about used functions: filter() and some()
You can use Array.prototype.some(), Array.prototype.every() to check each element of each array.
var ar = [
[2, 6, 89, 45],
[3, 566, 23, 79],
[434, 677, 9, 23]
];
var val = [3, 566, 23, 79];
var bool = ar.some(function(arr) {
return arr.every(function(prop, index) {
return val[index] === prop
})
});
console.log(bool);
I guess there is no such JS functionality available. but you can create one
function arrEquals( one, two )
{
if( one.length != two.length )
{
return false;
}
for( i = 0; i < one.length; i++ )
{
if( one[i] != two[i] )
{
return false;
}
}
return true;
}
The problem with this is that of object/array equality in Javascript. Essentially, the problem is that two arrays are not equal, even if they have the same values. You need to loop through the array and compare the members to your search key (val), but you'll need a way of accurately comparing arrays.
The easiest way round this is to use a library that allows array/object comparison. underscore.js has a very attractive method to do this:
for (var i = 0; i < ar.length; i++) {
if (_.isEqual(ar[i], val)) {
// value is present
}
}
If you don't want to use another library (though I would urge you to -- or at least borrow the message from the Underscore source), you could do this with JSON.stringify...
var valJSON = JSON.stringify(val);
for (var i = 0; i < ar.length; i++) {
if (valJSON === JSON.stringify(ar[i]) {
// value is present
}
}
This will almost certainly be significantly slower, however.
You can use toString convertion to compare elements
var ar = [
[2,6,89,45],
[3,566,23,79],
[434,677,9,23]
];
var val = [3,566,23,79];
s = !ar.every(a => (a.toString() != val.toString()));
console.log(s) // true
Use this instead
if (ar.join(".").indexOf(val) > -1) {
return true;
} else {
return false;
}
Use lodash isEqual
const isValIncludedInAr = ar.some(element => isEqual(element, val))
const arrayOne = [2,6,89,45];
const arrayTwo = [3,566,23,79];
const arrayThree = [434,677,9,23];
const data = new Set([arrayOne, arrayTwo, arrayThree]);
// Check array if exist
console.log( data.has(arrayTwo) ); // It will return true.
// If you want to make a set into array it's simple
const arrayData = [...data];
console.log(arrayData); // It will return [[2,6,89,45], [3,566,23,79], [434,677,9,23]]
Is there an easy way of knowing if and array contains all elements of another array?
Example:
var myarray = [1,2,3];
var searchinarray = [1,2,3,4,5];
searchinarray contains all elements of myarray, so this should return true.
Regards
Here is an implementation of that function:
function contains(a, s) {
for(var i = 0, l = s.length; i < l; i++) {
if(!~a.indexOf(s[i])) {
return false;
}
}
return true;
}
This shows that it does what you describe:
> var myarray = [1,2,3];
> var searchinarray = [1,2,3,4,5];
> contains(myarray, searchinarray)
false
> contains(myarray, [1,2])
true
> contains(myarray, [2,3])
true
A contains function should only visit members of the array to be contained that exist, e.g.
var myArray = [1,,2];
var searchInArray = [1,2,3];
contains(myArray, searchInArray);
should return true, however a simple looping solution will return false as myArray[1] doesn't exist so will return undefined, which is not present in the searchInArray. To easily avoid that and not use a hasOwnProperty test, you can use the Array every method:
function contains(searchIn, array) {
return array.every(function(v){return this.indexOf(v) != -1}, searchIn);
}
so that:
var a = [1,,3];
var s = [1,2,3,4,5];
console.log(contains(s, a)); // true
You can add a contains method to all instances of Array if you wish:
if (typeof Array.prototype.contains == 'undefined') {
Array.prototype.contains = function(a) {
return a.every(function(v, i) {
return this.indexOf(v) != -1;
}, this);
}
}
console.log(s.contains(a)); // true
console.log(s.contains([1,9])); // false
You may need a polyfill for browsers that don't have .every (IE 8?).
function compare(array, contains_array) {
for(var i = 0; i < array.length; i++) {
if(contains_array.indexOf(array[i]) == -1) return false;
}
return true;
}
compare(myarray, searchinarray);
Let's say we have the following js array
var ar = [
[2,6,89,45],
[3,566,23,79],
[434,677,9,23]
];
var val = [3,566,23,79];
Is there a js builtin function or jQuery one with which you can search the array ar for val?
Thanks
***UPDATE*************
Taking fusion's response I created this prototype
Array.prototype.containsArray = function(val) {
var hash = {};
for(var i=0; i<this.length; i++) {
hash[this[i]] = i;
}
return hash.hasOwnProperty(val);
}
you could create a hash.
var ar = [
[2,6,89,45],
[3,566,23,79],
[434,677,9,23]
];
var hash = {};
for(var i = 0 ; i < ar.length; i += 1) {
hash[ar[i]] = i;
}
var val = [434,677,9,23];
if(hash.hasOwnProperty(val)) {
document.write(hash[val]);
}
You can also use a trick with JSON serializing. It is short and simple, but kind of hacky.
It works, because "[0,1]" === "[0,1]".
Here is the working demo snippet:
Array.prototype.indexOfForArrays = function(search)
{
var searchJson = JSON.stringify(search); // "[3,566,23,79]"
var arrJson = this.map(JSON.stringify); // ["[2,6,89,45]", "[3,566,23,79]", "[434,677,9,23]"]
return arrJson.indexOf(searchJson);
};
var arr = [
[2,6,89,45],
[3,566,23,79],
[434,677,9,23]
];
document.body.innerText = arr.indexOfForArrays([3,566,23,79]);
function indexOfArray(val, array) {
var hash = {};
for (var i = 0; i < array.length; i++) {
hash[array[i]] = i;
}
return (hash.hasOwnProperty(val)) ? hash[val] : -1;
};
I consider this more useful for than containsArray(). It solves the same problem (using a hash table) but returns the index (rather than only boolean true/false).
Can you try this?
var ar = [
[2,6,89,45],
[3,566,23,79],
[434,677,9,23]
];
var val = [3,566,23,79];
var sval = val.join("");
for(var i in ar)
{
var sar = ar[i].join("");
if (sar==sval)
{
alert("found!");
break;
}
}
Why don't you use javascript array functions?
function filterArrayByValues(array, values) {
return array.filter(function (arrayItem) {
return values.some(function (value) {
return value === arrayItem;
});
});
}
Or if your array is more complicated, and you want compare only one property but as result return whole object:
function filterArrayByValues(array, values, propertyName) {
return array.filter(function (arrayItem) {
return values.some(function (value) {
return value === arrayItem[propertyName];
});
});
}
More about used functions: filter() and some()
You can use Array.prototype.some(), Array.prototype.every() to check each element of each array.
var ar = [
[2, 6, 89, 45],
[3, 566, 23, 79],
[434, 677, 9, 23]
];
var val = [3, 566, 23, 79];
var bool = ar.some(function(arr) {
return arr.every(function(prop, index) {
return val[index] === prop
})
});
console.log(bool);
I guess there is no such JS functionality available. but you can create one
function arrEquals( one, two )
{
if( one.length != two.length )
{
return false;
}
for( i = 0; i < one.length; i++ )
{
if( one[i] != two[i] )
{
return false;
}
}
return true;
}
The problem with this is that of object/array equality in Javascript. Essentially, the problem is that two arrays are not equal, even if they have the same values. You need to loop through the array and compare the members to your search key (val), but you'll need a way of accurately comparing arrays.
The easiest way round this is to use a library that allows array/object comparison. underscore.js has a very attractive method to do this:
for (var i = 0; i < ar.length; i++) {
if (_.isEqual(ar[i], val)) {
// value is present
}
}
If you don't want to use another library (though I would urge you to -- or at least borrow the message from the Underscore source), you could do this with JSON.stringify...
var valJSON = JSON.stringify(val);
for (var i = 0; i < ar.length; i++) {
if (valJSON === JSON.stringify(ar[i]) {
// value is present
}
}
This will almost certainly be significantly slower, however.
You can use toString convertion to compare elements
var ar = [
[2,6,89,45],
[3,566,23,79],
[434,677,9,23]
];
var val = [3,566,23,79];
s = !ar.every(a => (a.toString() != val.toString()));
console.log(s) // true
Use this instead
if (ar.join(".").indexOf(val) > -1) {
return true;
} else {
return false;
}
Use lodash isEqual
const isValIncludedInAr = ar.some(element => isEqual(element, val))
const arrayOne = [2,6,89,45];
const arrayTwo = [3,566,23,79];
const arrayThree = [434,677,9,23];
const data = new Set([arrayOne, arrayTwo, arrayThree]);
// Check array if exist
console.log( data.has(arrayTwo) ); // It will return true.
// If you want to make a set into array it's simple
const arrayData = [...data];
console.log(arrayData); // It will return [[2,6,89,45], [3,566,23,79], [434,677,9,23]]