Compare two arrays and remove partially matched strings [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 11 days ago.
Improve this question
i'm having trouble filtering an array based on partially matched content from another.
var arrayComplete = [
'blue.house',
'blue.bird',
'blue.ocean',
'red.chair',
'red.curtain',
'black.screen',
'green.grass',
'green.parrot'
];
var arrayToRemove = [blue, red];
I need to end up with an array that had elements removed based on partial string matchs:
For example, in this case, based on having the colours "blue" and "red" all elements that had "blue" and "red" on their string were removed
['black.screen','green.grass','green.parrot'];
Any tips?
I'm trying
let newArray = arrayComplete.filter((e) => arrayToRemove.includes(e))
But returns empty array. I assume because it's not matching partial strings.

Here is how to do it with Array#filter and String#includes methods:
const
arrayComplete = [ 'blue.house', 'blue.bird', 'blue.ocean', 'red.chair', 'red.curtain', 'black.screen', 'green.grass', 'green.parrot' ],
arrayToRemove = ['blue', 'red'],
output = arrayComplete
.filter(value => !arrayToRemove.some(st => value.includes(st)));
console.log( output );
Alternatively .....
If your aim was to exclude strings that start with <color>. where <color> is an element of arrayToRemove then you can use String#startsWith instead of String#includes as follows:
const
arrayComplete = [ 'blue.house', 'blue.bird', 'blue.ocean', 'red.chair', 'red.curtain', 'black.screen', 'green.grass', 'green.parrot', 'green.credenza' ],
arrayToRemove = ['blue', 'red'],
output = arrayComplete
.filter(value => !arrayToRemove.some(st => value.startsWith(`${st}.`)));
console.log( output );

Go over the elements, split them at the dot and check if any of the parts are contained in the excluded elements:
var arrayComplete = [
'blue.house',
'blue.bird',
'blue.ocean',
'red.chair',
'red.curtain',
'black.screen',
'green.grass',
'green.parrot'
];
var arrayToRemove = ['blue', 'red'];
const f = (arr, els) => arr.filter(it => it.split('.').every(v => !els.includes(v)))
console.log(f(arrayComplete, arrayToRemove))
Or if you want to avoid split, you can use a regex which tests for the appearance of the excluded word (check that it is surrounded by word boundaries with \b)
var arrayComplete = [
'blue.house',
'blue.bird',
'blue.ocean',
'red.chair',
'red.curtain',
'black.screen',
'green.grass',
'green.parrot'
];
var arrayToRemove = ['blue', 'red'];
const f = (arr, els) => arr.filter(it => !els.map(el => new RegExp('\\b'+el+'\\b')).some(regex => regex.test(it)))
console.log(f(arrayComplete, arrayToRemove))

let originalArray = ['blue.house','blue.bird','blue.ocean','red.chair','red.curtain','black.screen','green.grass','green.parrot'];
var arrayToRemove = ['blue','red']
originalArray = originalArray.filter((e) => !(e.includes(arrayToRemove[0]) || e.includes(arrayToRemove[1] )))
console.log(originalArray)
this will work only if you have fixed no of items to be remove

You could take a nested approach nd filter by looking the to unwanted strings and check if they exist, then remove this item.
const
arrayComplete = ['blue.house', 'blue.bird', 'blue.ocean', 'red.chair', 'red.curtain', 'black.screen', 'green.grass', 'green.parrot'],
arrayToRemove = ['blue', 'red'],
result = arrayComplete.filter(s => !arrayToRemove.some(r => s.includes(r)));
console.log(result);

One way to do this is by using the following filter() criteria:
string => !arrayToRemove.some(part => string.includes(part))
!array.some(...) might be a bit confusing. There is every(), some(), but for some reason JavaScript doesn't have none().
!array.some() is the equivalent of the non-existent array.none(). For a better understanding you could see the above as:
// none of the `arrayToRemove` elements partially matches the string
string => arrayToRemove.none(part => string.includes(part))
// concept JavaScript ^^^^ doesn't actually exisit
const arrayComplete = [
'blue.house',
'blue.bird',
'blue.ocean',
'red.chair',
'red.curtain',
'black.screen',
'green.grass',
'green.parrot'
];
const arrayToRemove = ['blue', 'red'];
const filtered = arrayComplete.filter((string) => (
!arrayToRemove.some(part => string.includes(part))
));
console.log(filtered);

Related

JS: sorting based on multiple arrays

I have following three arrays, which defines the order of some texts
arr1 = ['ab', 'bc', 'ca', 'ac']
arr2 = ['lm', 'mn', 'ml']
arr3 = ['ij', 'kj', 'pr']
I want to sort array below based on the array above. Each string of myArray is consists of 5 characters where each 2 character are from the characters of the above 3 arrays. That is, arr1 has the highest priority, arr2 has priority over arr3 but less priority than arr1. arr3 has the lowest priority.
First 2 character of each string in myArray always match at least one string in arr1, middle two character match arr2 and last two character match arr3.
myArray = ['acmnkj', 'bcmlij', 'camnij', 'bcmnij',]
How can I sort myArray so that the results are sorted by arr1, arr2 and arr3. Expected sorted array ['bcmnij', 'bcmlij', 'camnij', 'acmnkj']
How can do this?
const arr1 = ['ab', 'bc', 'ca', 'ac']
const arr2 = ['lm', 'mn', 'ml']
const arr3 = ['ij', 'kj', 'pr']
const myArr = ['acmnkj', 'bcmlij', 'camnij', 'bcmnij']
const f = (s,a,i)=>a.indexOf(s.substring(2*i,2*i+2))
myArr.sort((x,y)=>[arr1,arr2,arr3].reduce((a,c,i)=>a || f(x,c,i)-f(y,c,i),0))
console.log(myArr)
You could take an object with the order of the parts and compare sliced parts against.
const
arr1 = ['ab', 'bc', 'ca', 'ac'],
arr2 = ['lm', 'mn', 'ml'],
arr3 = ['ij', 'kj', 'pr'],
data = ['acmnkj', 'bcmlij', 'camnij', 'bcmnij'],
order = Object.fromEntries([...arr1, ...arr2, ...arr3].map((v, i) => [v, i + 1]));
data.sort((a, b) => {
let i = 0;
while (i < 6) {
const r = order[a.slice(i, i + 2)] - order[b.slice(i, i + 2)];
if (r) return r;
i += 2;
}
return 0;
});
console.log(data);
A slightly different approach with replacing the strings by an order value for comparing by string.
const
getOrder = s => s.replace(/../g, k => order[k]),
arr1 = ['ab', 'bc', 'ca', 'ac'],
arr2 = ['lm', 'mn', 'ml'],
arr3 = ['ij', 'kj', 'pr'],
data = ['acmnkj', 'bcmlij', 'camnij', 'bcmnij'],
order = Object.fromEntries([...arr1, ...arr2, ...arr3].map((v, i) => [v, (i + 1).toString().padStart(2)]));
data.sort((a, b) => getOrder(a).localeCompare(getOrder(b)));
console.log(order)
console.log(data);
You could create an object which maps the priority for each array
createOrder = (arr) => Object.fromEntries(arr.map((c,i) => [c,i]))
and then create an array of orders.
orders = [arr1,arr2,arr3].map(createOrder)
I'm assuming that there could be duplicate strings within the arrays. So, a flat order object is not created.
// orders array
[
{
"ab": 0,
"bc": 1,
"ca": 2,
"ac": 3
},
{
"lm": 0,
"mn": 1,
"ml": 2
},
{
"ij": 0,
"kj": 1,
"pr": 2
}
]
Then sort your array. Get the parts for each string
const partsA = a.match(/.{2}/g)
This can be changed based on your actual data. Here, it matches every 2 characters. If your input is 'ac-mn-kj', you'd be splitting at -.
Then loop until you find a difference in the order of each parts using some.
This works for any number of input arrays or format of the string in myArray
const arr1 = ['ab', 'bc', 'ca', 'ac'],
arr2 = ['lm', 'mn', 'ml'],
arr3 = ['ij', 'kj', 'pr'],
createOrder = (arr) => Object.fromEntries(arr.map((c,i) => [c,i])),
orders = [arr1,arr2,arr3].map(createOrder),
myArray = ['acmnkj', 'bcmlij', 'camnij', 'bcmnij']
myArray.sort((a,b) => {
const partsA = a.match(/.{2}/g) // can change based on your requirement
const partsB = b.match(/.{2}/g)
let returnValue;
partsA.some((p, i) => returnValue = orders[i][p] - orders[i][partsB[i]])
return returnValue
})
console.log(myArray)

How to create a nested while loop based on N number of arrays?

I'm trying to create a combination of all possible variants of the arrays given below, which are pretty self-explanatory.
let arr1 = ['Small', 'Medium', 'Large', 'Extra-Large']
let arr2 = ['Black','Red','White']
let arr3 = ['Normal','Limited-Edition']
let combos = []
arr1.forEach((i) => {
arr2.forEach((j) => {
arr3.forEach((k) => {
combos.push(i + '-' + j + '-' + k)
})
})
})
console.log(combos)
This gives the output I want, however I want to create a function that takes an arbitrary array of arrays, [arr1, arr2, arr3.....arrN] and creates a nested loop of each of them, and returns a combined value of strings.
How do I go around creating such a function?
You can use something like this using reduce. I referenced this post
let arr1 = ['Small', 'Medium', 'Large', 'Extra-Large']
let arr2 = ['Black','Red','White']
let arr3 = ['Normal','Limited-Edition']
let arr4 = ['x','y','z']
let arr = [arr1,arr2,arr3,arr4]
let combined = arr.reduce((a,c)=>{
return a.flatMap(x=>c.map(y=>x.concat(y)))
},[[]]).map((z) => z.join("-"))
console.log(combined)
console.log(combined.length) //4*3*2*3 = 72
UPDATE - This one is taken directly from the top answer with a very small modification
let arr1 = ['Small', 'Medium', 'Large', 'Extra-Large']
let arr2 = ['Black','Red','White']
let arr3 = ['Normal','Limited-Edition']
let arr4 = ['x','y','z']
let arr = [arr1,arr2,arr3,arr4]
const cartesian =
(a) => a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat()))).map(x=>x.join("-"));
console.log(cartesian(arr))
const arr1 = ['Small', 'Medium', 'Large', 'Extra-Large']
const arr2 = ['Black','Red','White']
const arr3 = ['Normal','Limited-Edition']
const arr4 = ['x','y','z']
const arr = [arr1,arr2,arr3,arr4]
const merged = [].concat.apply([], arr);
console.log(merged);

Distinct values from array based on a part of the string in JS

I have the following array:
var array= [
'http://www.example.com/page1/#comment-1234',
'http://www.example.com/page1/#comment-98733',
'http://www.example.com/page1/#comment-4298312',
'http://www.example.com/page2/#comment-2143'
]
I would like to distinct this array to return just with:
//['http://www.example.com/page1','http://www.example.com/page2']
How would I do this with JS?
Appreciate the help!
slice the base url and then use includes.
var array = [
'http://www.example.com/page1/#comment-1234',
'http://www.example.com/page1/#comment-98733',
'http://www.example.com/page1/#comment-4298312',
'http://www.example.com/page2/#comment-2143'
];
const output = [];
array.forEach((url) => {
const base = url.slice(0, 28);
if (!output.includes(base)) output.push(base);
});
console.log(output);
-- Edit--
var array = [
'http://www.example.com/page1/#comment-1234',
'http://www.example.com/page123/#comment-98733',
'http://www.example.com/page1/#comment-4298312',
'http://www.example.com/page2/#comment-2143'
];
const output = [];
array.forEach((url) => {
const idx = url.lastIndexOf('/');
const base = url.slice(0, idx);
if (!output.includes(base)) output.push(base);
});
console.log(output);
You should use reduce method of array in javascript, like this
var array = [
'http://www.example.com/page1/#comment-1234',
'http://www.example.com/page1/#comment-98733',
'http://www.example.com/page1/#comment-4298312',
'http://www.example.com/page2/#comment-2143'
]
const newArr = array.reduce((newArray, value) => {
const url = value.replace(/\/#.*$/, "")
if (newArray.indexOf(url) === -1) {
newArray.push(url)
}
return newArray;
}, []);
console.log(newArr)
You can use new Set() to get rid of duplicate elements in an array.
First step, create an array consisting of the URLs without the hashbangs. I'm using split for this.
const URLs = array.map(URL => URL.split('/#')[0]);
You can remove duplicates from that by passing it into a set, then spreading the result back into an array.
const uniques = [...new Set(URLs)];
Lastly, if you want a more robust method to get the part before the hashbang (e.g. if some URLs contain https), look into using URL. https://developer.mozilla.org/en-US/docs/Web/API/URL
const array= [
'http://www.example.com/page1/#comment-1234',
'http://www.example.com/page1/#comment-98733',
'http://www.example.com/page1/#comment-4298312',
'http://www.example.com/page2/#comment-2143'
];
const URLs = array.map(URL => URL.split('/#')[0]);
const uniques = [...new Set(URLs)];
console.log(uniques);
var array= [
'http://www.example.com/page1/#comment-1234',
'http://www.example.com/page1/#comment-98733',
'http://www.example.com/page1/#comment-4298312',
'http://www.example.com/page2/#comment-2143'
];
var results = array.map(function(url){
var index = url.indexOf("#");
return url.substr(0, index);
});
var disctinctResult = [...new Set(results)]
You can use URL objects to remove the hashes and then, filter out the duplicates. Here is an example:
const array = [
'http://www.example.com/page1/#comment-1234',
'http://www.example.com/page1/#comment-98733',
'http://www.example.com/page1/#comment-4298312',
'http://www.example.com/page2/#comment-2143'
];
const result = array.map(str => {
const url = new URL(str);
return `${url.origin}${url.pathname}`
}).filter((urlStr, index, arr) => arr.indexOf(urlStr) !== index);
console.log(result);
So, you can also use regular expressions, to remove unwanted part of string.
var array= [
'http://www.example.com/page1/#comment-1234',
'http://www.example.com/page1/#comment-98733',
'http://www.example.com/page1/#comment-4298312',
'http://www.example.com/page2/#comment-2143'
]
const mapped = array.map(item => item.replace(/\/\#comment-[0-9]{0,}/, ''))
console.log(mapped);
// ["http://www.example.com/page1", "http://www.example.com/page1",
// "http://www.example.com/page1", "http://www.example.com/page2"]

How to compare two arrays or strings in javascript?

I have a array1 from checkboxes selected, and i need to compare with the most similar, how i do that?
var array1 = ["pain", "fever", "vomit"]
var array2 = ["diarrhea", "fever", "vomit", "embolism", "bleeding"]
var array3 = ["diarrhea", "tumor", "vomit", "cold", "bleeding"]
I tried some methods but they only return me as "true" or "false", I would like to get the most similar array1
You could count the number of similar elements using reduce, then order your arrays by similarity and take the first element:
const array1 = ["pain", "fever", "vomit"];
const array2 = ["diarrhea", "fever", "vomit", "embolism", "bleeding"];
const array3 = ["diarrhea", "tumor", "vomit", "cold", "bleeding"];
const countSimilarElements = (arr1, arr2) => arr1.reduce((count, x) => count + arr2.includes(x), 0);
const orderBySimilarity = (arr1, ...arr) =>
arr.map(x => ({ array: x, similarity: countSimilarElements(arr1, x) }))
.sort((a, b) => b.similarity - a.similarity);
const ordered = orderBySimilarity(array1, array2, array3);
console.log(ordered);
console.log(ordered[0].array);
This function takes in a the array you want to compare as the 'base' and a list of other arrays as 'arr_list', then returns a similarity array showing how similar each array in 'arr_list' was to the 'base'. This way you can compare multiple arrays with a single call and know reference their similarity by referencing the index of the returned similarity array.
const a = ['11', '22', '33'], b = ['11', '44', '55', '66'], c = ['55', '33', '11', '22'], d = ['11', '66', '44', '22'];
const Similarity = (base, arr_list) => {
let similarity = new Array(arr_list.length).fill(0);//creates similarity array which defaults to 0
base.forEach( el => {
arr_list.forEach( (arr, i) => similarity[i] += arr.includes(el) )
});
return similarity;
}
const similarity = Similarity(a, [b,c,d])
console.log(similarity)

How to union two arrays with ordering?

I have a few arrays I want to union, but I need to keep them in order.
Example:
var js_files = [
'bower_components/jquery/dist/jquery.js',
'bower_components/jquery.cookie/jquery.cookie.js',
'bower_components/jquery-placeholder/jquery-placeholder.js',
'bower_components/foundation-sites/dist/foundation.js',
'bower_components/Swiper/dist/js/swiper.jquery.min.js',
'assets/scripts/**/*.js'
];
and:
var js_files = [
'bower_components/jquery/dist/jquery.js',
'parnet/bower_components/jquery/dist/jquery.js',
'parent/bower_components/jquery.cookie/jquery.cookie.js'
];
and I want union them and make sure the fist array will stay first & remove duplicate values.
expected outotput:
['bower_components/jquery/dist/jquery.js',
'bower_components/jquery.cookie/jquery.cookie.js',
'bower_components/jquery-placeholder/jquery-placeholder.js',
'bower_components/foundation-sites/dist/foundation.js',
'bower_components/Swiper/dist/js/swiper.jquery.min.js',
'assets/scripts/**/*.js',
'parnet/bower_components/jquery/dist/jquery.js',
'parent/bower_components/jquery.cookie/jquery.cookie.js']
Can I do this using _.union? Any other idea?
You could use Set in combination with the spread syntax ... for unique items in original sort order.
var js_files1 = [
'abc',
'def',
'bower_components/jquery/dist/jquery.js',
'bower_components/jquery.cookie/jquery.cookie.js',
'bower_components/jquery-placeholder/jquery-placeholder.js',
'bower_components/foundation-sites/dist/foundation.js',
'bower_components/Swiper/dist/js/swiper.jquery.min.js',
'assets/scripts/**/*.js'
],
js_files2 = [
'def',
'ghi',
'bower_components/jquery/dist/jquery.js',
'parnet/bower_components/jquery/dist/jquery.js',
'parent/bower_components/jquery.cookie/jquery.cookie.js'
],
uniqueFiles = [...new Set([...js_files1, ...js_files2])];
console.log(uniqueFiles);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do this in the ES5 fashion using Array.prototype.slice eg :
const first = [1,2,3,4];
const second = [5,6,7,8];
const results = [].concat(first.slice(), second.slice());
Or the ESNext fashion using "desctructuring"
const first = [1,2,3,4];
const second = [5,6,7,8];
const result = [...first, ...second];
Edit : I missed the point that you need distinct values;
This will remove dupes from results after you concatenated stuff.
const distinctResults = results.filter(function removeDuplicates(item, index){
return results.indexOf(item) === index;
});
var a = [1,2,3];
var b = [4,5,6];
var Joined = [...a,...b];
Similarly can do for your code.
just use Array.prototype.concat
var js_files1 = [
'bower_components/jquery/dist/jquery.js',
'bower_components/jquery.cookie/jquery.cookie.js',
'bower_components/jquery-placeholder/jquery-placeholder.js',
'bower_components/foundation-sites/dist/foundation.js',
'bower_components/Swiper/dist/js/swiper.jquery.min.js',
'assets/scripts/**/*.js'
];
var js_files2 = [
'parnet/bower_components/jquery/dist/jquery.js',
'parent/bower_components/jquery.cookie/jquery.cookie.js'
];
var res = js_files1.concat(js_files2);
console.log(res);
var js_files1 = [
'bower_components/jquery/dist/jquery.js',
'bower_components/jquery.cookie/jquery.cookie.js',
'bower_components/jquery-placeholder/jquery-placeholder.js',
'bower_components/foundation-sites/dist/foundation.js',
'bower_components/Swiper/dist/js/swiper.jquery.min.js',
'assets/scripts/**/*.js'
];
var js_files2 = [
'parnet/bower_components/jquery/dist/jquery.js',
'parent/bower_components/jquery.cookie/jquery.cookie.js',
"assets/scripts/**/*.js"
];
js_files2.forEach(value => {
if (js_files1.indexOf(value) == -1) {
js_files1.push(value);
}
});
console.log(js_files1);
_.union will remove duplicate values from your second array.
In your case you dont have any duplicate value in second array so it will simply concat them
But if you have any duplicate value in second array, _.union will remove it
for eg.
var a = [
'bower_components/jquery/dist/jquery.js',
'bower_components/jquery.cookie/jquery.cookie.js',
'bower_components/jquery-placeholder/jquery-placeholder.js',
'bower_components/foundation-sites/dist/foundation.js',
'bower_components/Swiper/dist/js/swiper.jquery.min.js',
'assets/scripts/**/*.js'
];
var b = [
'bower_components/jquery/dist/jquery.js',
'parnet/bower_components/jquery/dist/jquery.js',
'parent/bower_components/jquery.cookie/jquery.cookie.js'
];
_.union(a, b) will result in
[
"bower_components/jquery/dist/jquery.js",
"bower_components/jquery.cookie/jquery.cookie.js",
"bower_components/jquery-placeholder/jquery-placeholder.js",
"bower_components/foundation-sites/dist/foundation.js",
"bower_components/Swiper/dist/js/swiper.jquery.min.js",
"assets/scripts/**/*.js",
"parnet/bower_components/jquery/dist/jquery.js",
"parent/bower_components/jquery.cookie/jquery.cookie.js"
]
Here you can see _.union removes duplicate value "bower_components/jquery/dist/jquery.js" of array B in the result

Categories

Resources