How to kill duplicates in array without using Set? - javascript

How can i delete all duplicates in array without using Set (because it will disturb the order)
And why my loop with splice method doesnt work?
let result = [
'j', 'a', 'a', 'v',
'a', 'a', 's', 'c',
'r', 'i', 'p', 't'
]
;
for (let i = 0; i < result.length; i++) {
if (result[i] === result[i + 1]){
result.splice(result.indexOf(result[i]), 1);
}
}
console.log(result) //[ "j", "v", "a", "a", "s", "c", "r", "i", "p", "t" ]
expected output - > [ "j", "a", "v", "a", "s", "c", "r", "i", "p", "t" ]

You could filter the array and have a look to the predecessor.
const
data = ['j', 'a', 'a', 'v', 'a', 'a', 's', 'c', 'r', 'i', 'p', 't'],
result = data.filter((v, i, a) => v !== a[i - 1]);
console.log(...result);

Your method fails in your condition:
if (result[i] === result[i + 1])
Because you only check to see if the next item is the same as the current item and not against the entire array.
To solve this you can create a new array and push in this array only the values that are not already there, thus eliminating duplicates.
const result2 = [];
for (let i = 0; i < result.length; i += 1) {
if (result2.indexOf(result[i])>-1) {
continue;
}
result2.push(result[i]);
}

I think to remove duplicate from an array write a function that do the job and return the array with unique item in it. Please find the below code that serve the propose.
function removeDuplicate(data) {
const tempArray = [];
data.forEach( (item) => {
if (tempArray.indexOf(item) === -1) {
tempArray.push(item);
}
});
return tempArray;
}
let result = [
'j', 'a', 'a', 'v',
'a', 'a', 's', 'c',
'r', 'i', 'p', 't'
];
result = removeDuplicate(result );

Related

Can't find the longest occurancy in a set of duplicates

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.

best way to check element combination exist in array in typescript

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

remove common elements between multiple arrays

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);

Randomize Text (JS) in Input (HTML) on Reload

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

JavaScript - Find a word string out of strings in an array

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));

Categories

Resources