How can I get one unique value in an array or string? Only the first value. Pure JS only.
My example:
function searchValue () {
let inputText = [1,1,4,2,2,2,3,1];
let foundedValue;
for (let i = 0; i < inputText.length; i++) {
if (i === inputText.indexOf(inputText[i]) && i === inputText.lastIndexOf(inputText[i])) {
foundedValue = inputText[i];
break;
} else {
foundedValue = "not founded.";
}
}
return foundedValue;
}
console.log("Search value: "+ searchValue())
Answer is 4.
But, I need a short solution. Using the find() and filter() functions.
You can find the first unique item in your array using find() and comparing indexOf() to lastIndexOf() to determine whether or not there is more than one instance of an item in the array. If you need to find unique characters in a string, then you can first split it into an array and then use the same approach.
const arr = [1, 1, 4, 2, 2, 2, 3, 1];
const result = arr.find((x) => arr.indexOf(x) === arr.lastIndexOf(x));
console.log(result);
// 4
const text = 'aadbbbca';
const textarr = text.split('');
const textresult = textarr.find((x) => textarr.indexOf(x) === textarr.lastIndexOf(x));
console.log(textresult);
// d
You can try this.
const arr = [1, 1, 4, 2, 2, 2, 3, 1];
let r = {};
arr.map(a => r[a] = (r[a] || 0) +1)
var res = arr.find(a => r[a] === 1 )
console.log(res)
You can use js Set() object.
At first you could create a Set of duplicated elements.
const inputText = [1,1,4,2,2,2,3,1];
const duplicatesSet= inputText.reduce((dupSet, el) =>
inputText.filter(arrEl => arrEl === el).length > 1 ?
dupSet.add(el) : dupSet
, new Set());
Second you could use array.find. It returns first duplicated element.
const firstDupElement = inputText.find(el => duplicatesSet.has(el));
const searchValue = (_param) => {
for (let i= 0; i < _param.length; i+= 1) {
if (_param.indexOf(_param[i]) === _param.lastIndexOf(_param[i])) return _param[i];
}
return "not founded.";
}
let arr = [1,1,2,2,2,1,3,1,4,4,5]
const dupelearray = (array) => {
let arr2 =[...arr]
let ele = []
let state = false
arr2.map((i,index)=>{
arr2.splice(index,1)
arr.map((j)=>{
return arr2.includes(j) ? null : state=true
})
state && ele.push(i)
state=false
arr2.splice(index,0,i)
})
return console.log(arr.indexOf(ele[0]))
}
dupelearray(arr)
wow i didnt knew lastindexof method and was making this algo so difficult
btw this solution also works but definitely i am new in algo so this will take much more time but the solution still works!!!!!! damn should remember more methods or you have to think so much -_-
Related
I have a array of string.
let arr=["robin","rohit","roy"];
Need to find all the common character present in all the strings in array.
Output Eg: r,o
I have tried to create a function for above case with multiple loops but i want to know what should be the efficient way to achive it.
Here's a functional solution which will work with an array of any iterable value (not just strings), and uses object identity comparison for value equality:
function findCommon (iterA, iterB) {
const common = new Set();
const uniqueB = new Set(iterB);
for (const value of iterA) if (uniqueB.has(value)) common.add(value);
return common;
}
function findAllCommon (arrayOfIter) {
if (arrayOfIter.length === 0) return [];
let common = new Set(arrayOfIter[0]);
for (let i = 1; i < arrayOfIter.length; i += 1) {
common = findCommon(common, arrayOfIter[i]);
}
return [...common];
}
const arr = ['robin', 'rohit', 'roy'];
const result = findAllCommon(arr);
console.log(result);
const arr = ["roooooobin","rohit","roy"];
const commonChars = (arr) => {
const charsCount = arr.reduce((sum, word) => {
const wordChars = word.split('').reduce((ws, c) => {
ws[c] = 1;
return ws;
}, {});
Object.keys(wordChars).forEach((c) => {
sum[c] = (sum[c] || 0) + 1;
});
return sum;
}, {});
return Object.keys(charsCount).filter(key => charsCount[key] === arr.length);
}
console.log(commonChars(arr));
Okay, the idea is to count the amount of times each letter occurs but only counting 1 letter per string
let arr=["robin","rohit","roy"];
function commonLetter(array){
var count={} //object used for counting letters total
for(let i=0;i<array.length;i++){
//looping through the array
const cache={} //same letters only counted once here
for(let j=0;j<array[i].length;j++){
//looping through the string
let letter=array[i][j]
if(cache[letter]!==true){
//if letter not yet counted in this string
cache[letter]=true //well now it is counted in this string
count[letter]=(count[letter]||0)+1
//I don't say count[letter]++ because count[letter] may not be defined yet, hence (count[letter]||0)
}
}
}
return Object.keys(count)
.filter(letter=>count[letter]===array.length)
.join(',')
}
//usage
console.log(commonLetter(arr))
No matter which way you choose, you will still need to count all characters, you cannot get around O(n*2) as far as I know.
arr=["robin","rohit","roy"];
let commonChars = sumCommonCharacters(arr);
function sumCommonCharacters(arr) {
data = {};
for(let i = 0; i < arr.length; i++) {
for(let char in arr[i]) {
let key = arr[i][char];
data[key] = (data[key] != null) ? data[key]+1 : 1;
}
}
return data;
}
console.log(commonChars);
Here is a 1 liner if anyone interested
new Set(arr.map(d => [...d]).flat(Infinity).reduce((ac,d) => {(new RegExp(`(?:.*${d}.*){${arr.length}}`)).test(arr) && ac.push(d); return ac},[])) //{r,o}
You can use an object to check for the occurrences of each character. loop on the words in the array, then loop on the chars of each word.
let arr = ["robin","rohit","roy"];
const restWords = arr.slice(1);
const result = arr[0].split('').filter(char =>
restWords.every(word => word.includes(char)))
const uniqueChars = Array.from(new Set(result));
console.log(uniqueChars);
Javascript's filter returns the array with all the elements passing the test.
How how can you easily get all the elements that failed the test without running the test again, but for the converse? How is the best way to do it, even if you have to run the test again.
let arr; // this is the array on which the filter will be run [SET ELSEWHERE]
let fn; // The filter function [SET ELSEWHERE]
let goodElements; // This will be the new array of the good elements passing the test
let badElements; // This will be the new array of the elements failing the test
goodElements = arr.filter(fn);
// SO HOW IS badElements set????
How is badElements set?
If you don't want to do two iterations, you can use a for loop and a ternary operator:
let arr = [1, 2, 3];
let fn = (e) => e % 2 == 0;
let goodElements = [];
let badElements = [];
for(const e of arr) (fn(e) ? goodElements : badElements).push(e);
console.log(goodElements);
console.log(badElements);
Otherwise, just invert the condition with the ! operator:
let arr = [1, 2, 3];
let fn = (e) => e % 2 == 0;
let goodElements;
let badElements;
goodElements = arr.filter(fn);
badElements = arr.filter(e => !fn(e));
console.log(goodElements);
console.log(badElements);
Don't use filter(). If you want to partition the data into two arrays, do it yourself.
function partition(array, fn) {
let goodArray = [],
badArray = [];
array.forEach(el => {
if (fn(el)) {
goodArray.push(el);
} else {
badArray.push(el);
}
});
return [goodArray, badArray];
}
let [goodElemements, badElements] = partition(arr, fn);
You could also use reduce()
function partition(array, fn) {
return array.reduce(acc, el => {
if (fn(el)) {
acc[0].push(el);
} else {
acc[1].push(el);
}
}, [[],[]]);
}
let [goodElemements, badElements] = partition(arr, fn);
If you want to do this strictly with Array.filter and only one loop, then consider something like this:
UPD: based on #AlvaroFlaƱoLarrondo comment, added external condition function to current approach.
// Array of elements
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
// External filter method
const fn = e => e.length > 6;
// Define empty bad array
const bad = [];
// Define good array as result from filter function
const good = words.filter(word => {
// In filter condition return good values
if(fn(word)) return word;
// And skip else values by just pushing them
// to bad array, without returning
else bad.push(word);
});
// Results
console.log(good);
console.log(bad);
You could use reduce in order to split the array into two arrays based on a predicate, like in this example:
const arr = [1, 0, true, false, "", "foo"];
const fn = element => !element;
const [goodElements, badElements] = arr.reduce(
([truthies, falsies], cur) =>
fn(cur) ? [truthies, [...falsies, cur]] : [[...truthies, cur], falsies],
[[], []]
);
console.log(goodElements, badElements);
I see two possible routes:
// in this case, if it's not in `goodElements`, it's a bad 'un
badElements = arr.filter( el => !goodElements.includes(el) );
or this:
// we don't **know** if fn needs the optional parameters, so we will
// simply pass them. If it doesn't need 'em, they'll be ignored.
badElements = arr.filter( (el, idx, arr) => !fn(el, idx, arr) );
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
const fn = (x) => x % 2 === 0
const removeItems = (array, itemsToRemove) => {
return array.filter(v => {
return !itemsToRemove.includes(v);
});
}
const goodElements = arr.filter(fn)
console.log(goodElements) // [ 0, 2, 4, 6, 8 ]
const badElements = removeItems(arr, goodElements)
console.log(badElements) // [ 1, 3, 5, 7, 9 ]
I have an array and I want to delete some elements. My array is arrayAuxiliar. My code is the following one:
for( var i = 0; i < arrayAuxiliar.length; i++)
{
if (arrayAuxiliar[i] == valueFirts) {
arrayAuxiliar.splice(i,1);
}
else if(arrayAuxiliar[i] == value){
arrayAuxiliar.splice(i,1);
}
}
Example of what is happening:
Initial values: arrayAuxiliar = [3,2,1], valueFirst = 1, value = 2
Final values: arrayAuxiliar = [3,1]
I know this happens because splice() changes the original array and that's for this reason the comparasion between arrayAuxiliar[i] == valueFirts is never true. I've also tried to use remove arrayAuxiliar[i] but it returns [3,,].
How can I solve this situation in order to get the only element that does not verify the conditions which is 3? The idea was the final result be [3] and I could get it by a arrayAuxiliar[0] command.
Use filter and includes method
const array = [3, 2, 1]
const remove_list = [2, 1]
const res = array.filter(num => !remove_list.includes(num))
console.log(res)
I think using filter would be more appropiate. You can try:
let arrayAuxiliar = [3, 2, 1]
const valueFirst = 1
const value = 2
arrayAuxiliar = arrayAuxiliar.filter(i => i !== valueFirst && i !== value)
console.log(arrayAuxiliar)
I would use Array.prototype.filter():
const arr = [3,2,1];
const valueFirst = 1;
const value = 2;
console.log(arr.filter(item => ![value, valueFirst].includes(item)));
Also you can use reduce function
function test(arrayAuxiliar, valueFirts, value) {
return arrayAuxiliar.reduce((acc,rec) => {
if ((rec === value) || (rec === valueFirts)) {
return [...acc]
}
return [...acc, rec]
}, [])
}
console.log(test([3,2,1,4,1,2,2,3,1,4,5,8,2,5], 1, 2))
The problem is to find the unique number in a array such as [2,2,2,5].
The output should be 5 as it is the 1 unique element in the array.
I have attempted this:
function findUniq(arr) {
var b= arr[0];
var c;
for(var i=0; i<arr.length; i++)
{
if(arr[i]===b )
{
b=arr[i]
}
else
{
c=arr[i];
}
}
return c
console.log(findUniq([3, 5, 3, 3, 3]))
This works fine unless the unique number is the first element in the array. How do I fix this?
You can use indexOf and lastIndexOf to see if a value occurs more than once in the array (if it does, they will be different), and if so, it is not the unique value. Use filter to process the array:
let array = [2,2,2,5];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
array = [5,3,3,3,3];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
array = [4,4,5,4];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
You can create a recursive function that will take the first element of the array and see if it exists in the rest of it, if it does, it will take the next element and do the same, return the element if it doesn't exist in the rest of the array :
const arr = [3, 3, 3, 5, 3];
const find = arr => {
const [f, ...rest] = arr;
if(rest.includes(f))
return find(rest);
else
return f;
}
const result = find(arr);
console.log(result);
Note that this will return the last element if all of them are the same [3,3,3] will return 3
Try something like this using a set, which only stores unique elements:
var set = new Set(arr);
// count instances of each element in set
result = {};
for(var i = 0; i < a.length; ++i) {
if(!result[arr[i]])
result[arr[i]] = 0;
++result[arr[i]];
}
for (var value in result) {
if (value == 1) {
return value;
}
}
// if there isn't any
return false;
This should work, please tell me if it doesn't.
This is another implementation that is surely less efficient than that of #Nick's, but it is a valid algorithm anyway:
function findUniq(arr) {
var elemCount = new Map();
var uniq = [];
// Initialize elements conts
for (var k of arr.values()) {
elemCount.set(k, 0);
}
// Count elements
for (var k of arr.values()) {
elemCount.set(k, elemCount.get(k) + 1);
}
// Add uniq elements to array
for (var [k, v] of elemCount.entries()) {
if (v === 1) uniq.push(k);
}
return uniq;
}
console.log(findUniq([3, 5, 3, 3, 3]))
if you prefer .reduce over .map for your use case (for performance/etc. reasons):
function existance(data) {
return data.reduce((a, c) => (data.indexOf(c) === data.lastIndexOf(c)) ? a.concat(c) : a, []);
}
console.log(existance([1,1,1,2]));
console.log(existance([1,1,2,3,4,5,5,6,6,6]));
I want to filter one value from my first array and create a second array with the filtered value.
So far I have that but it does not seem very efficient.
const blacklist = bookingsList.filter(booking => booking.id === id);
const newBookingList = bookingsList.filter(booking => booking.id !== id);
Is there a better way to do this?
I think something like this would be good on a large array or if testing the condition is expensive because you would only loop through the array once
const array1 = [];
const array2 = [];
for (var i = 0; i < input.length; i++) {
const value = input[i];
( testCondition(value) ? array1 : array2 ).push(value);
}
You can do it with a single iteration by using forLoop like
const blacklist = [];
const newBookingList = [];
bookingsList.forEach(booking => {
if(booking.id === id) {
blacklist.push(booking)
}
else {
newBookingList.push(booking)
}
}
You can use forEach() and ternary operator:
const bookingsList = [{id:'black'},{id:'new'}];
const blacklist = [], newBookingList = [], id='black';
bookingsList.forEach(booking => booking.id === id? blacklist.push(booking.id) : newBookingList.push(booking.id));
console.log(blacklist);
console.log(newBookingList);
let blacklist = []
let newBookingList = []
const ID = 10;
let bookingsList=[{id:10}, {id:20}]
bookingsList.forEach(booking => booking.id === ID ? blacklist.push(booking) : newBookingList.push(booking))
console.log(newBookingList)
console.log(blacklist)
I think you can use forEach for that:
const newBookingList = [];
const blacklist = [];
bookingsList.forEach(function(booking) {
if(booking.id === id){
blacklist.push(booking)
}
if(booking.id !== id){
newBookingList.push(booking)
}
})
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
You can use splice method to retrive and remove filtered value.
var bookingList = [{id : 1, name : "A"}, {id: 2, name: "B"}];
var sBookingList = bookingList.splice(bookingList.map(function(b){return b.name}).indexOf("A"), 1);
console.log(sBookingList);
console.log(bookingList);