I have a problem to compare two 2D arrays in javascript.
It should output "true" if the two 2D arrays are the same.
The code I tried:
`
function check(){
if (data.every() === solution.every()){
alert("example");
} else {
console.log("Data Array: " + data);
console.log("Solution Array: " + solution);
}
}
`
I think my solution only works with two 1D arrays. I hope someone can help me and teach me something.
Note: I only use jquery and nativ js.
Thanks in advance.
~Luca
I would assume something like this would work :
function test(array1, array2)
{
if(array1.length !== array2.length) return false;
for(let i=0;i<array1.length;i++)
{
if(array1[i].length !== array2[i].length) return false;
for(let j=0;j<array1[i].length;j++)
{
if(array1[i][j] !== array2[i][j]) return false;
}
}
return true;
}
You could also do a recursive version that would work for array of N-dimensions, but it you need only 2, the above is fine.
This code will work for any number of dimensions:
const random2dArray = (n,m) => Array(n).fill(0)
.map(_=>Array(m).fill(0).map(_=>10*Math.random()|0))
const arrEq = (a,b) => Array.isArray(a) ?
a.length===b.length && a.every((e,i)=>arrEq(e,b[i])) : a===b
const a = random2dArray(3,3)
const b = random2dArray(3,3)
const c = random2dArray(3,5)
const d = random2dArray(6,7)
const e = structuredClone(a)
console.log(arrEq(a,b))
console.log(arrEq(a,c))
console.log(arrEq(a,d))
console.log(arrEq(a,e))
You can simply achieve this requirement by following below steps :
flatten both the 2D arrays into a 1D array.
Check the length of both the arrays along with the each item check using Array.every() method.
Live Demo :
const data = [[1,2,3], [4,5]];
const solution = [[1,2,3], [4,5]];
const res = (data.flat().length === solution.flat().length) && data.flat().every((item, index) => item === solution.flat()[index]);
console.log(res ? 'Both arrays are equal' : 'not equal');
A common solution that many people suggest is to use JSON.stringify(). This allows us to serialize each array and then compare the two serialized strings. A simple implementation of this might look something like this:
function check(){
if ( JSON.stringify(data) === JSON.stringify(solution) ){
alert("example");
} else {
console.log("Data Array: " + data);
console.log("Solution Array: " + solution);
}
}
Related
I have an Array and i would like to Filter or delete the following urls from my Array every time they appear:
"https://basueUrl.com/Claim"
"https://basueUrl.com/ExplanationOfBenefit"
My Array
Array= [
"https://basueUrl.com/Patient"
"https://basueUrl.com/Organization"
"https://basueUrl.com/Claim"
"https://basueUrl.com/Practitioner"
"https://basueUrl.com/Encounter"
"https://basueUrl.com/Condition"
"https://basueUrl.com/Claim"
"https://basueUrl.com/ExplanationOfBenefit"
"https://basueUrl.com/Claim"
"https://basueUrl.com/ExplanationOfBenefit"
"https://basueUrl.com/ExplanationOfBenefit"
]
First Solution I have tried for loop but did not work?
for( var i = 0; i < Array.length; i++){
if ( Array[i] === "https://basueUrl.com/ExplanationOfBenefit" & "https://basueUrl.com/Claim") {
Array.splice(i, 1);
i--;
}
}
console.log(Array);
Second Solution I tried making a remove method did not work either.
function arrayRemove(Array, value) {
return Array.filter(function(ele){
return ele != value;
});
}
var result = arrayRemove(Array,"https://basueUrl.com/ExplanationOfBenefit" & "https://basueUrl.com/Claim");
Any suggestion please?
The first approach is modifying the array while the loop is being executed, which generates problem with the index because the array.length changes when you call Array.prototype.splice.
In the second approach, you're not passing what you think
console.log("https://basueUrl.com/ExplanationOfBenefit" & "https://basueUrl.com/Claim");
// A number? probably you want an array.
You can use the function filter and the function includes as follow:
let skip = ["https://basueUrl.com/Claim", "https://basueUrl.com/ExplanationOfBenefit"];
let arr = ["https://basueUrl.com/Patient","https://basueUrl.com/Organization","https://basueUrl.com/Claim","https://basueUrl.com/Practitioner","https://basueUrl.com/Encounter","https://basueUrl.com/Condition","https://basueUrl.com/Claim","https://basueUrl.com/ExplanationOfBenefit","https://basueUrl.com/Claim","https://basueUrl.com/ExplanationOfBenefit","https://basueUrl.com/ExplanationOfBenefit"];
let result = arr.filter(url => !skip.includes(url));
console.log(result);
Array.filter(x => x !== "https://basueUrl.com/Claim" && x !== "https://basueUrl.com/ExplanationOfBenefit")
var Array= [
"https://basueUrl.com/Patient",
"https://basueUrl.com/Organization",
"https://basueUrl.com/Claim",
"https://basueUrl.com/Practitioner",
"https://basueUrl.com/Encounter",
"https://basueUrl.com/Condition",
"https://basueUrl.com/Claim",
"https://basueUrl.com/ExplanationOfBenefit",
"https://basueUrl.com/Claim",
"https://basueUrl.com/ExplanationOfBenefit",
"https://basueUrl.com/ExplanationOfBenefit"
];
var filteredArray = Array.filter(item => item !== "https://basueUrl.com/Claim" && item !== "https://basueUrl.com/ExplanationOfBenefit")
console.log(filteredArray)
You can run the code below. Hope this helps.
// use this array instead on the original. It creates a new array from the original
// array.
const newFilteredArray = Array.filter(url => url !== 'https://basueUrl.com/Claim' &&
url !== 'https://basueUrl.com/ExplanationOfBenefit');
Please see below the way you can achieve the above mentioned scenario.
arr.filter(ele=>ele!=="https://basueUrl.com/Claim"
&& ele!=="https://basueUrl.com/ExplanationOfBenefit");
I am trying to only return 1's from this array but I am having trouble figuring out whats wrong with my code.
let arr = [[1],[1,2],[3],[1,2],[4],[1,2],[1]];
let ok = arr.filter((x) => {
if(x.length > 1){
return x.filter((y) => {
return y == 1;
})
}else{
return x == 1;
}
})
console.log(ok);
Your inner x.filter returns a new filtered array. But that is not really used as it is passed to the outer filter, which will then take that to decide wether to filter the outer one. So actually it seems as the outer filter should actually map:
let ok = arr.map(inner => inner.filter(el => el === 1));
You also do not need that if statement as the code works nevertheless.
Jonas gave a very good answer above, though I'm not sure this is what was asked. I have a feeling :) that you need only arrays which were exactly [1] in the original array arr. If so:
const arr = [[1],[1,2],[3],[1,2],[4],[1,2],[1]];
const ok = arr.filter(el => el.length === 1 && el[0] === 1) // [[1], [1]]
I have two two-dimensional array.
var arr1=[[1,20],[2,30]];
var arr2=[[2,40],[3,50]];
This is expected output:
[[1,20,null],[2,30,40],[3,null,50]]
It is like full join of two data frames. The logic is similar to this pseudo code:
df1.join(df2, df1[col_1] == df2[col_1], 'full')
but this case is for two-dimensional array. Can lodash do this? If not, how to do it in vanilla javascript?
Well, lodash can't do this, but we can:
function flatten2d(arr1, arr2) {
const o1 = _.fromPairs(arr1);
const o2 = _.fromPairs(arr2);
const result = [];
_.forEach(o1, (v, k) => {
const v2 = o2[k] || null;
result.push([k|0, v, v2]);
delete o2[k];
});
// at this point, only items non-existing
// in o1 are left in o2
_.forEach(o2, (v, k) => {
result.push([k|0, null, v]);
});
return result;
}
Testing:
flatten2d([[1,20],[2,30]], [[2,40],[3,50]])
Result:
[[1,20,null], [2,30,40], [3,null,50]]
If you don't have duplicate id's in any single array then you can try combine them, and group them using groupBy with first element (i.e. the key 0), and if you have duplicates, anyway I am not sure what exactly output you are looking for! Here is what you can do:
_(arr1.concat(arr2)).groupBy('0').map(v=>
[v[0][0]].concat(v.length > 1 ? v.map(m=>m[1]) : [v[0][1], null])
).value();
Here is an working snippet for you:
var arr1=[[1,20],[2,30]];
var arr2=[[2,40],[3,50]];
var res = _(arr1.concat(arr2)).groupBy('0').map(v=>
[v[0][0]].concat(v.length > 1 ? v.map(m=>m[1]) : [v[0][1],null])
).value();
console.log(JSON.stringify(res));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
I need to remove all the duplicate elements, for example:
var arr = [
{'seriesIndex':1,pointIndex:0},
{'seriesIndex':1,pointIndex:1},
{'seriesIndex':0,pointIndex:0},
{'seriesIndex':1,pointIndex:0},
{'seriesIndex':1}
]
How to remove redundant (duplicate) array objects from an array?
My expected output is:
arr = [
{'seriesIndex':1,pointIndex:0},
{'seriesIndex':1,pointIndex:1},
{'seriesIndex':0,pointIndex:0},
{'seriesIndex':1}
]
How to achieve this?
In vanilla Javascript, I'd suggest to keep track of the encountered composite keys while iterating on the list in a .reduce() method. The test on prv.key[key] is O(1) (hashtable lookup), so this algorithm is O(n).
var arr = [
{seriesIndex:1, pointIndex:0},
{seriesIndex:1, pointIndex:1},
{seriesIndex:0, pointIndex:0},
{seriesIndex:1, pointIndex:0},
{seriesIndex:1}
];
arr = arr.reduce(function(prv, cur) {
var key = cur.seriesIndex + '/' + cur.pointIndex;
if(!prv.key[key]) {
prv.key[key] = true;
prv.res.push(cur);
}
return prv;
}, {key: {}, res: []}).res;
console.log(arr);
I use library, which has rich API - lodash
With lodash it looks like :
_.uniqWith(arr, _.isEqual)
It is simple and short
Link to library https://lodash.com/
By an invention of Object.prototype.compare() you may do like this
Object.prototype.compare = function(o){
var ok = Object.keys(this);
return typeof o === "object" && ok.length === Object.keys(o).length ? ok.every(k => this[k] === o[k]) : false;
};
var arr = [{'seriesIndex':1,pointIndex:0},
{'seriesIndex':1,pointIndex:1},
{'seriesIndex':0,pointIndex:0},
{'seriesIndex':1,pointIndex:0},
{'seriesIndex':1}
],
result = arr.reduce((res,obj) => res.length === 0 ? res.concat(obj)
: !!res.find(o => obj.compare(o)) ? res
: res.concat(obj),[]);
console.log(JSON.stringify(result,null,2));
I need to check if a string has one of three substrings, and if yes, to implement a function. I know I can check for one substring using if (str.indexOf("term1") >= 0) but is there a way to check for multiple substrings short of using several instances of this code?
TIA
if (/term1|term2|term3/.test("your string")) {
//youre code
}
This achieves dynamically and elegantly what you are trying to do
const terms = ["term1", "term2", "term3"]
const str = "very large string to check for term1, tern2, etc ..."
// check if the string has some of the terms
const result1 = terms.some(term => str.includes(term))
// check if the string has all the terms
const result2 = terms.every(term => str.includes(term))
This also makes it easy to filter an array of strings for an array of substrings
const terms = ["term1", "term2", "term3"]
const strings = ["very large string text ....", "another large string text"]
// filter the strings of the array that contain some of the substrings we're looking for
const result1 = strings.filter(str => terms.some(term => str.includes(term)))
// filter the strings of the array that contain all the substrings we're looking for
const result2 = strings.filter(str => terms.every(term => str.includes(term)))
You could use a loop. Maybe even create a helper function like so:
function ContainsAny(str, items){
for(var i in items){
var item = items[i];
if (str.indexOf(item) > -1){
return true;
}
}
return false;
}
Which you can then call like so:
if(ContainsAny(str, ["term1", "term2", "term3"])){
//do something
}
Maybe this:
if (str.indexOf("term1") >= 0 || str.indexOf("term2") >= 0 || str.indexOf("term3") >= 0)
{
//your code
}
The .map() function can be used to convert an array of terms into an array of booleans indicating if each term is found. Then check if any of the booleans are true.
Given an array of terms:
const terms = ['term1', 'term2', 'term3'];
This line of code will return true if string contains any of the terms:
terms.map((term) => string.includes(term)).includes(true);
Three examples:
terms.map((term) => 'Got term2 here'.includes(term)).includes(true); //true
terms.map((term) => 'Not here'.includes(term)).includes(true); //false
terms.map((term) => 'Got term1 and term3'.includes(term)).includes(true); //true
Or, if you want to wrap the code up into a reusable hasTerm() function:
const hasTerm = (string, terms) =>
terms.map(term => string.includes(term)).includes(true);
hasTerm('Got term2 here', terms); //true
hasTerm('Not here', terms); //false
hasTerm('Got term1 and term3', terms); //true
Try it out:
https://codepen.io/anon/pen/MzKZZQ?editors=0012
.map() documentation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Note:
This answer optimizes for simplicity and readability. If extremely large arrays of terms are expected, use a loop that short-circuits once a term is found.
You can do something like
function isSubStringPresent(str){
for(var i = 1; i < arguments.length; i++){
if(str.indexOf(arguments[i]) > -1){
return true;
}
}
return false;
}
isSubStringPresent('mystring', 'term1', 'term2', ...)
If you want to check for multiple string matches and highlight them, this code snippet works.
function highlightMatch(text, matchString) {
let textArr = text.split(' ');
let returnArr = [];
for(let i=0; i<textArr.length; i++) {
let subStrMatch = textArr[i].toLowerCase().indexOf(matchString.toLowerCase());
if(subStrMatch !== -1) {
let subStr = textArr[i].split('');
let subStrReturn = [];
for(let j=0 ;j<subStr.length; j++) {
if(j === subStrMatch) {
subStrReturn.push('<strong>' + subStr[j]);
} else if (j === subStrMatch + (matchString.length-1)){
subStrReturn.push(subStr[j] + '<strong>');
} else {
subStrReturn.push(subStr[j]);
}
}
returnArr.push(subStrReturn.join(''));
} else {
returnArr.push(textArr[i]);
}
}
return returnArr;
}
highlightMatch('Multi Test returns multiple results', 'multi');
=> (5) ['<strong>Multi<strong>', 'Test', 'returns', '<strong>multi<strong>ple', 'results']