Related
The target is to detect superstring in a set of arrays. In this case it should be 'bal' but I get 'lbal'.
const arr = [
['g', 'l', 'o', 'b', 'a', 'l'],
['b','a','l','l']
]
const res = argv.reduce((acc, val) => acc.filter(elem => val.includes(elem)))
This function just gives ALL duplicates(items that are presented in any array) when I need only the most long duplicate sequence. Any suggestions?
you can create an object that counts how many times an element is present in the array of array
like this
const arr = [
['a', 'b', 'm'],
['g', 'o', 'a', 'b'],
['w', 'o', 'u', 'k', 'a', 'b']
]
const countTimes = data => data.flat().reduce((res, v) => {
return {
...res,
[v]: (res[v] || 0 ) + 1
}
}, {})
const duplicates = data => Object.entries(countTimes(data))
.filter(([v, n]) => n > 1)
.map(([v, n]) => v)
console.log(countTimes(arr))
console.log(duplicates(arr) )
const original = [
['a', 'b', 'm'],
['g', 'o', 'a', 'b'],
['w', 'o', 'u', 'k', 'a', 'b']
]
// The easiest is to split up between unique results and duplicates
let uniqueValues = []
let duplicates = []
// Now we're going to loop every array
original.forEach((arr) => {
// Loop every value inside the array
arr.forEach((value) => {
// Check if we had this value already
if (!uniqueValues.includes(value)) {
uniqueValues.push(value)
} else {
duplicates.push(value)
}
})
})
console.log('Duplicates: ', duplicates)
// If you want remove the duplicates from the duplicates, use set
let uniqueDuplicates = [...new Set(duplicates)]
console.log('Unique duplicates: ', uniqueDuplicates)
If you don't have to know in which array duplicates are, you can use Array.prototype.flat() to get rid of nested arrays, then check simple array for duplicates.
const arr = [
['a', 'b', 'm'],
['g', 'o', 'a', 'b'],
['w', 'o', 'u', 'k', 'a', 'b']
]
const arr2 = arr.flat() // ['a', 'b', 'm', 'g', 'o', 'a', 'b', 'w', 'o', 'u', 'k', 'a', 'b']
const hasDuplicates = new Set(arr2).size !== arr2.length
you can create a tally, to find how many each element globally is duplicated by doing a nested forEach
function findDuplicates(data) {
const map = {};
data.forEach((row) => {
row.forEach((item) => {
if (!map[item]) {
map[item] = 1;
} else [map[item]++];
});
});
return map;
}
You can create a simple counter object (if you know python, this is similar to collections.Counter):
class Counter extends Map {
update(values) {
for (let val of values)
this.set(val, 1 + (this.get(val) ?? 0))
}
}
ARR = [
['a', 'b', 'm'],
['g', 'o', 'a', 'b'],
['w', 'o', 'u', 'k', 'a', 'b']
]
const tally = new Counter()
for (let subArray of ARR)
tally.update(new Set(subArray))
for (let [element, count] of tally)
if (count === ARR.length)
console.log(element)
count === yourArrayOfArrays.length selects elements that appear in all arrays, you can replace it with count > 1 to find any duplicates.
I have array with some element that I want to check if some element combination exist in array that target element is following by any element of checkingSet, if yes, then return true otherwise, return false. For example,
if inputArray is ['a', 'b', 'c', 'd'] and looking for combination is ['a', 'd'] then it should return true because inputArray has both in the right sequence.
if inputArray is ['d', 'b', 'c', 'd', 'a'] and the combination is ['a', 'd'], then it should be false because inputArray includes both elements but in wrong order
or
isExist(['a', 'd']) => true
isExist(['a', 'a', 'd']) => true
isExist(['e', 'd']) => false
I can use Set and while loop
but I am wondering if any more elegant or modern way to do?
export function isExist(checkArray): boolean {
let hasA = false;
let hasB = false;
checkingSet = new Set(['b', 'c', 'd'])
const target = 'a'
inputArray = [...checkArray]
while (inputArray && !!inputArray.length) {
const lastOne = inputArray.pop();
if (!hasA && !!lastOne) {
hasA = chekcingSet.has(lastOne);
}
if (!hasB && !!lastOne) {
hasB = lastOne === target;
}
if (hasA && hasB) {
return true;
}
}
return false;
}
To check that the array contains 'a', and after this 'a' at least one of ['b', 'c', 'd'] is in the array you can do this. First, get the index of the first 'a' in the array, then check if some value of ['b', 'c', 'd'] is included in that array after this start index.
function doesExist(arr) {
const startPos = arr.indexOf('a')
if (startPos < 0)
return false
return ['b', 'c', 'd'].some(char => arr.includes(char, startPos + 1))
}
console.log(doesExist(['a', 'd']))
console.log(doesExist(['a', 'a', 'd']))
console.log(doesExist(['e', 'd']))
console.log(doesExist(['d', 'a']))
This is the general version, it's O(n).
function doesDupleExistInOrder([el1, el2], arr) {
let index = arr.indexOf(el1)
if (index == -1) return false;
return arr.includes(el2, index + 1)
}
console.log(doesDupleExistInOrder(["a", "d"], ["a", "b", "c", "d", "e"])); // true
console.log(doesDupleExistInOrder(["a", "b"], ["a", "b", "c", "d", "e"])); // true
console.log(doesDupleExistInOrder(["d", "e"], ["a", "b", "c", "d", "e"])); // true
console.log(doesDupleExistInOrder(["d", "a"], ["a", "b", "c", "d", "e"])); // false
console.log(doesDupleExistInOrder(["d", "a"], ["a"])); // false
console.log(doesDupleExistInOrder(["d", "a"], [])); // false
If you want a specific version then just curry the general function AKA:
let doesADExist = arr => doesDupleExistInOrder(["a", "d"], arr);
console.log(doesADExist(["a", "b", "c", "d", "e"])); // true
I have 3 arrays (or more/less, it's not mandatory to be 3, I just gave an example) and I want to remove all the common elements between them. For example, between the first 2, the common elements are x and z, between the second and the third array the common element would be t. Between the first and the thirs the common element is k. Basically I want to remove any elements that appear more than 1 times in multiple arrays.
!! the first array can have common elements with the third one !!
Here is what I tried so far, but it's not working correctly.
let y = [{
id: 'a',
elems: ['x', 'y', 'z', 'k']
},
{
id: 'b',
elems: ['x', 't', 'u', 'i', 'z']
},
{
id: 'c',
elems: ['m', 'n', 'k', 'o', 't']
},
]
// x, z, t
for (let i = 0; i < y.length - 1; i++) {
let current = y[i].elems
let current2 = y[i + 1].elems
if (current[i] == current2[i]) {
const index = current.indexOf(current[i]);
if (index > -1) {
current.splice(index, 1);
current2.splice(index, 1);
}
}
}
console.log(y)
The desired result would be
[
{
"id": "a",
"elems": [
"y"
]
},
{
"id": "b",
"elems": [
"u",
"i"
]
},
{
"id": "c",
"elems": [
"m",
"n",
"o"
]
}
]
Which would be a correct and optimal solution for this? I also tried to concatenate the 3 arrays and remove the duplicates, but then I don't know how to recreate the 3 arrays back.. Thanks!
I would first loop over all the elems and count up how many times that have been seen. After that I would loop again and filter out anything that was seen more than once.
const myData = [{
id: 'a',
elems: ['x', 'y', 'z']
},
{
id: 'b',
elems: ['x', 't', 'u', 'i', 'z']
},
{
id: 'c',
elems: ['m', 'n', 'o', 't']
},
]
// count up every elem so we know which ones are duplicated
const allElems = myData.reduce((acc, item) => {
item.elems.forEach( key => {
acc[key] = acc[key] || 0;
acc[key]++;
});
return acc;
}, {})
// loop over all the elems and select only the elems that we have seen once
myData.forEach(item => {
item.elems = item.elems.filter(key => allElems[key] === 1);
})
console.log(myData)
let x = ['a', 'b']
let y = [{
id: 'a',
elems: ['x', 'y', 'z', 'k']
},
{
id: 'b',
elems: ['x', 't', 'u', 'i', 'z']
},
{
id: 'c',
elems: ['m', 'n', 'k', 'o', 't']
},
]
// x, z, t
for (let i = 0; i < y.length - 1; i++) {
for (let j = 1; j < y.length; j++) {
let current = y[i].elems
let current2 = y[j].elems
current2.forEach((item,index)=>{
if(current.includes(item)){
current.splice(current.indexOf(item),1)
current2.splice(index,1)
}
})
}
}
console.log(y)
.as-console-wrapper { max-height: 100% !important; top: 0; }
const y = [
{ id: 'a', elems: ['x', 'y', 'z'] },
{ id: 'b', elems: ['x', 't', 'u', 'i', 'z'] },
{ id: 'c', elems: ['m', 'n', 'o', 't'] },
];
// get number of occurences for each elem
const elems
= y.flatMap(e => e.elems).reduce((acc,elem) => {
acc[elem] = acc[elem] ? acc[elem]+1 : 1;
return acc;
}, {});
// get unique elems
const unique = Object.keys(elems).filter(elem => elems[elem]===1);
// remove non-unique elems from each item
const res = y.map(item =>
({ ...item, elems: item.elems.filter(e => unique.includes(e)) })
);
console.log(res);
Using a Map to track counts after one loop through then use the count of that Map in a filter for final results
let x = ['a', 'b']
let y = [{
id: 'a',
elems: ['x', 'y', 'z']
},
{
id: 'b',
elems: ['x', 't', 'u', 'i', 'z']
},
{
id: 'c',
elems: ['m', 'n', 'o', 't']
},
]
const counts = new Map()
// first iteration to count values
y.forEach(({ elems }) => elems.forEach(v => counts.set(v, (counts.get(v) || 0) + 1)));
// second iteration to filter out dups
y.forEach(e => e.elems = e.elems.filter(v => counts.get(v) === 1))
console.log(y)
Let me know if this works for you.
let y = [
{
id: "a",
elems: ["x", "y", "z", "k"],
},
{
id: "b",
elems: ["x", "t", "u", "i", "z"],
},
{
id: "c",
elems: ["m", "n", "x", "z", "t"],
},
];
// For every element in first array
for (let el of y[0].elems) {
//If we find that every other array includes it
if (y.every((obj) => obj.elems.includes(el))) {
//Remove it from all arrays
for (let obj of y) {
obj.elems = obj.elems.filter((x) => x !== el);
}
}
}
let y = [{
id: 'a',
elems: ['x', 'y', 'z']
},
{
id: 'b',
elems: ['x', 't', 'u', 'i', 'z']
},
{
id: 'c',
elems: ['m', 'n', 'o', 't']
},
];
//
const notExist = (x, arr) => !arr.find(el => el == x);
const restToArrays = (i, arr) => arr.reduce((a, b, index) => index == i ? a : [...a, ...b.elems], []);
const result = y.map((ligne, index, arr) => ({
id: ligne.id,
elems: ligne.elems.filter(v => notExist(v, restToArrays(index, arr)))
}))
console.log(result);
I want to randomize letters and numbers, something like
let r = Math.random().toString(36).substring(7);
console.log("random", r);
but insert it in a text input HTML field. I have already managed to plug in texts from a list, but I want it completely random and to follow with an #something.com.
For example, I want the input field, on every refresh to have something like the following:
8ut5fgh8#gmail.com
0okmnhy4#gmail.com
s5g7j9l0#gmail.com
The characters before the #gmail.com should be 8 chars long.
Thanks for your help. This is a snippet of what I have already done"
var texts = [
"#gmail.com",
"#yahoo.com",
"#xdxd.com"
];
document.getElementById('email0').value = texts[Math.floor(Math.random()*texts.length)];
E-mail: </br><input type="text" id="email0" name="email"><br>
If you figured out how to make a domain part - do the rest by analogy.
var texts = [
"#gmail.com",
"#yahoo.com",
"#xdxd.com"
];
var chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
function randomEmail(length) {
let result = ''
for (let i = 0; i <= length; i++) {
result += chars[Math.floor(Math.random() * chars.length)]
}
return result + texts[Math.floor(Math.random() * texts.length)]
}
document.getElementById('email0').value = randomEmail(8)
E-mail: <br><input type="text" id="email0" name="email"><br>
you can try this
var texts = [
"#gmail.com",
"#yahoo.com",
"#xdxd.com"
];
function random() {
var text = "";
var ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < 8; i++)
text += ch.charAt(Math.floor(Math.random() * ch.length));
return text;
}
let str = random()+texts[Math.floor(Math.random()*texts.length)];
document.getElementById('email0').value = str
<input id="email0">
this is another way to do it using arrays and join and assuming you only want small letters in your random emails.
let texts = [
"#gmail.com",
"#yahoo.com",
"#xdxd.com"
];
let alphnum = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
let randomChoice = [texts[Math.floor(Math.random() * texts.length)]]
for (let index = 0; index < 8; index++) {
const element = alphnum[Math.floor(Math.random() * alphnum.length)];
randomChoice.unshift(element)
}
let randomChoiceString = randomChoice.join("")
document.getElementById('email0').value = randomChoiceString
I am trying to find a word from consecutive strings inside an array and I am stuck at the moment.
For example: array = ['w', 'r', 'a', 'p', 'p', 'l', 'e', 'f', 'k', 'l']; I want to make a function that will return true if the word 'apple' is inside this array. Strings need to be consecutive.
array1 = ['w', 'r', 'a', 'p', 'l', 'p', 'e', 'f', 'k', 'l']; function for this kind of strings with no consecutive 'apple' strings should return false.
Can you help please?
array = ["w", "r", "a", "p", "p", "l", "e", "f", "k", "l"];
console.log(array.toString().replace(/,/g,"").indexOf("apple")>-1);
One approach would be traverse your array, and get substrings of length that equals the length of the matching substring, and compare the substring with the matching substring
for (int i=0; i<array.length-matching.length; i++) {
if (array.substr(i, i+matching.length) == matching) return true;
} return false;
Try this:
var array = ['w', 'r', 'a', 'p', 'p', 'l', 'e', 'f', 'k', 'l'];
function findWord(arr, word) {
return arr.join('').indexOf(word) !== -1;
}
// test
console.log('apple: ', findWord(array, 'apple'))
console.log('dog: ', findWord(array, 'dog'))
check this function:
function hasWord(inputSourceList, inputWord) {
return inputSourceList.join('').indexOf(inputWord) > -1;
};
With Array.join(), String.replace() and String.indexOf() functions:
var contains_word = function(arr, w) {
return arr.join('').replace(new RegExp('[^' + w + ']', 'g'), '')
.indexOf(w) !== -1;
}
console.log(contains_word(['w', 'r', 'a', 'p', 'l', 'p', 'e', 'f', 'k', 'l'], 'apple'));
console.log(contains_word(['w', 'r', 'a', 'p', 'p', 'l', 'e', 'f', 'k', 'l'], 'apple'));
You can use a combination of Array.every(), and Array.indexOf() to check if all letters are found in the correct order:
const findWordInArray = (word, array) => {
let last = -1; // stores the last index found
// iterate the letters of the word
return [...word].every((c) => {
// search for the letter from the last known position + 1 onwards
const index = array.indexOf(c, last + 1);
last = index; // change last to the new found position
return index !== -1;
});
}
const array1 = ['w', 'r', 'a', 'p', 'p', 'l', 'e', 'f', 'k', 'l'];
const array2 = ['w', 'r', 'a', 'p', 'l', 'p', 'e', 'f', 'k', 'l'];
const word = 'apple';
console.log(findWordInArray(word, array1));
console.log(findWordInArray(word, array2));