I am trying to work on a problem where I want to remove all the occurrences of similar value in an array
eg.
var sampleArr = ["mary","jane","spiderman","jane","peter"];
and I am trying to get result as => ["marry","spiderman","peter"]
how do I get this?
You can use filter()
var arr = ["mary","jane","spiderman","jane","peter"];
var unique = arr.filter((x, i) => arr.indexOf(x) === i);
console.log(unique);
var sampleArr = ["mary","jane","spiderman","jane","peter"];
var unique = [];
var itemCount = {};
sampleArr.forEach((item,index)=>{
if(!itemCount[item]){
itemCount[item] = 1;
}
else{
itemCount[item]++;
}
});
for(var prop in itemCount){
if(itemCount[prop]==1){
unique.push(prop);
}
}
console.log(unique);
Check this.
You can count the frequency of the character and just pick the character whose frequency is 1.
const arr = ["mary","jane","spiderman","jane","peter"];
frequency = arr.reduce((o,ch) => {
o[ch] = (o[ch] || 0) + 1;
return o;
}, {}),
unique = Object.keys(frequency).reduce((r,k) => frequency[k] === 1? [...r, k]: r, []);
console.log(unique);
You can use filter:
var sampleArr = ["mary","jane","spiderman","jane","peter"];
var result = sampleArr.filter((e,_,s)=>s.filter(o=>o==e).length<2);
// or with reduce and flatmap
const result1 = Object.entries(sampleArr.reduce((a,e)=>(a[e]??=0, a[e]++, a),{})).flatMap(([k,v])=>v==1 ? k: []);
console.log(result)
console.log(result1);
lot of solution, here easy solution to understand using match to have the occurence and filter to eliminate:
var arr = ['ab','pq','mn','ab','mn','ab'];
var st = arr.join(",");
result = arr.filter(it => {
let reg = new RegExp(it, 'g');
return st.match(reg).length == 1;
});
console.log(result);// here ["pq"]
filter seems to be your best bet here if you need extremely robust performance. No real need for jQuery in this instance. Personally, I would opt for readability for something like this and instead sort, set duplicates to null, and then remove all null values.
var sampleArr = ["mary","jane","spiderman","jane","peter"];
var result = sampleArr.sort().forEach((value, index, arr) => {
// if the next one is the same value,
// set this one to null
if(value === arr[value + 1])
return arr[index] = null;
// if the previous one is null, and the next one is different,
// this is the last duplicate in a series, so should be set to null
if(arr[value - 1] === arr[index + 1] !== value)
return arr[index] = null;
return
})
.filter(value => value === null) //remove all null values
console.log(result);
Related
It is a simple exercise that I am doing for mere practice and leisure, I have done it in various ways but I was wondering if there is an even more practical way or to reduce the lines of code making use of the many methods of JavaScript.
The exercise is about receiving an array (arr) and a number (target) and returning another array with a pair of numbers found in 'arr' whose sum is equal to 'target'.
function targetSum3(arr, target) {
let newArr = [];
let copyArray = arr;
for (let i of copyArray) {
let x = Math.abs(i - target);
copyArray.pop(copyArray[i]);
if (copyArray.includes(x) && (copyArray.indexOf(x) != copyArray.indexOf(i))) {
newArr.push(i);
newArr.push(x);
return newArr;
}
}
return newArr;
}
If you are fine with a function that just returns a pair of numbers (the first match so to speak) whose sum equals the targets value, this might be enough:
function sumPair (arr, target) {
while(arr.length) {
let sum1 = arr.shift();
let sum2 = arr.find(val => sum1 + val === target);
if (sum2) return [sum2, sum1];
}
return null;
}
const targetSum = (arr, target) => {
const first = arr.find((v,i,a) => arr.includes(target-v) && (arr.indexOf(target-v) !== i));
return first ? [first, target - first] : null;
};
const values = [1,2,3,4,5,6,7,8,9];
console.log(targetSum(values, 1)); // null
console.log(targetSum(values, 2)); // null
console.log(targetSum(values, 3)); // [1, 2]
console.log(targetSum(values, 15)); // [6, 9]
console.log(targetSum(values, 20)); // null
I changed for loop with forEach (more efficient) and there is no need for the copyArray array so I removed it. I also changed pop() with shift(), I think you want to shift the array and not pop-it (if I understand the task correctly).
function targetSum3(arr, target) {
let newArr = [];
arr.forEach(element => {
let x = Math.abs(element - target); // calc x
arr.shift(); // removes first element from arr (current element)
if (arr.includes(x) && (arr.indexOf(x) != arr.indexOf(element))) {
newArr.push(element);
newArr.push(x);
return;
}
});
return newArr;
}
use Array.filter to find the target sum for all values in an given array. See comments in the snippet.
sumsForTargetInArray();
document.addEventListener(`click`,
evt => evt.target.id === `redo` && sumsForTargetInArray());
function sumsInArray(arr, target) {
// clone the array
const clone = arr.slice();
let result = [];
while (clone.length) {
// retrieve the current value (shifting it from the clone)
const current = clone.shift();
// filter arr: all values where value + sum = target
const isTarget = arr.filter(v => current + v === target);
// add to result.
// Sorting is to prevent duplicates later
if (isTarget.length) {
result = [...result, ...isTarget.map(v => [current, v].sort())];
}
}
// weed out duplicates (e.g. 0 + 3, 3 + 0)
const unique = new Set();
result.forEach(r => unique.add(`${r[0]},${r[1]}`));
// return array of array(2)
return [...unique].map(v => v.split(`,`).map(Number));
}
function sumsForTargetInArray() {
const testArr = [...Array(20)].map((_, i) => i);
const target = Math.floor(Math.random() * 30);
document.querySelector(`pre`).textContent = `testArray: ${
JSON.stringify(testArr)}\ntarget: ${target}\nResult: ${
JSON.stringify(sumsInArray(testArr, target))}`;
}
<pre></pre>
<button id="redo">Again</button>
I want to check if all the integers present in a number has the same frequency.
Sample Input :
1212
Sample Output :
True
I am able to get the frequency using reduce function . But not able to compare the values.
let countOccurrences = arr => arr.reduce((accm,x)=> (accm[x] = ++accm[x] || 1,accm),{});
var obj = (countOccurrences([2,3,4,2,3,4]))
for(var i in obj)
console.log(obj[i+1]);
if(obj[i]===obj[i+1]){
console.log("true");
}else{
console.log("false");
}
//end-here
});
One way would be to use the Array every() method to check that every value in your object is equal to the first one (after converting to an array of values).
const countOccurrences = arr => arr.reduce((accm,x)=> (accm[x] = ++accm[x] || 1,accm),{});
const obj = countOccurrences([2,3,4,2,3,4]);
const same = Object.values(obj).every((el, _, arr) => el === arr[0]);
console.log(same);
You can use Set to remove dupicates
let countOccurrences = arr => arr.reduce((accm,x)=> (accm[x] = ++accm[x] || 1,accm),{});
var obj = (countOccurrences([2,3,4,2,3,4]));
const isSameFrequency = (new Set(Object.values(obj))).size == 1;
console.log(isSameFrequency);
While I'm sure I'm waay over-complicating things, I'm curious to know how I would "collapse" an array by combining all adjacent strings, but leaving objects as objects so that:
array = ["I","want","to",[Obj],"come","together"]
outputs
["I want to", [Obj], "come together"];
I feel like array.reduce() might be the ticket here, but I'm still wrapping my head around that function.
Reduce the array. If the current item and the last item in the accumulator (r) are strings, concatenate them. If not, push the current item to the accumulator:
const array = ["I","want","to",[{}],"come","together"]
const isString = s => typeof s === 'string'
const result = array.reduce((r, o) => {
if(isString(o) && isString(r[r.length - 1])) {
r[r.length - 1] = `${r[r.length - 1]} ${o}`
} else {
r.push(o)
}
return r
}, [])
console.log(result)
I would do this:
const array = ["I","want","to",{},"come","together"];
let outputArr = [];
let strArr = [];
array.forEach(elem => {
if (typeof elem === 'string') {
return strArr.push(elem);
}
outputArr.push(strArr.join(' '));
strArr = [];
outputArr.push(elem);
});
outputArr.push(strArr.join(' '));
console.log(outputArr);
In case you wanna go with the plain old for-loop :)
var result = [], array = ["I","want","to",{a: 1, b:2},"come","together"];
var i=0;var str = "";
for(; i< array.length; i++){
if(typeof array[i] === 'object' ){
result.push(str);
result.push(array[i]);
str="";
}else{
str = str+" "+ array[i];
}
}
if(i==array.length){
result.push(str);
}
console.log(result);
I have an array of strings like this:
const strings = [
"author:app:1.0.0",
"author:app:1.0.1",
"author:app2:1.0.0",
"author:app2:1.0.2",
"author:app3:1.0.1"
];
And I want to filter them so that only the ones that have the latest versions for the given "author:name" are left, thus removing ones that are not the latest (i.e. the "1.0.1" ones).
My expected result is this:
const filteredStrings = [
"author:app:1.0.1",
"author:app2:1.0.2",
"author:app3:1.0.1"
];
Any way to do this simply?
You can do it with two loops first one find new ones second one check which is bigger
const strings = [
"author:app:1.0.0",
"author:app:1.0.1",
"author:app2:1.0.0",
"author:app2:1.0.2",
"author:app3:1.0.1"
];
filteredones = [];
strings.forEach(element => {
var arr = element.split(":");
var isnew = true;
var found = filteredones.find(function(element2) {
var x = element2.split(":");
return x[1] == arr[1] && x[0] == arr[0]
});
if (found == undefined) {
filteredones.push(element);
}
});
for (var i = 0; i < filteredones.length; i++) {
element = filteredones[i];
var arr = element.split(":");
var isnew = true;
var found = strings.find(function(element2) {
var x = element2.split(":");
return x[1] == arr[1] && x[0] == arr[0] && x[2] > arr[2]
});
if (found != undefined) {
filteredones[i] = found;
}
};
console.log(filteredones);
you can check the value in the last index of the string in each of the elements of the array and if they qualify as a latest one put it to a new array.
You can use an object to store the key/version pairs, and convert to appropriate output on the end. The version comparison can be any of those found here: How to compare software version number using js? (only number)
result = {};
for (var s of input) {
// parts = ["author", "appname", "version"]
var parts = s.split(":");
var i = parts[0] + ":" + parts[1];
if (!result[i] || compareVersion(parts[2], result[i]))
// If not present or version is greater
result[i] = parts[2]; // Add to result
}
result = Object.keys(result).map(k => k + ":" + result[k])
Working demo: https://codepen.io/bortao/pen/LYVmagK
Build an object with keys as app name.
getValue method is calculate the version value so that to compare.
Update object value, when you see the version is recent (value is big).
const strings = [
"author:app:1.0.0",
"author:app:1.0.1",
"author:app2:1.0.0",
"author:app2:1.0.2",
"author:app3:1.0.1"
];
const filter = data => {
const res = {};
const getValue = item =>
item
.split(":")[2]
.split(".")
.reduceRight((acc, curr, i) => acc + curr * Math.pow(10, i), 0);
data.forEach(item => {
const app = item
.split(":")
.slice(0, 2)
.join(":");
if (!res[app] || (app in res && getValue(item) > getValue(res[app]))) {
res[app] = item;
}
});
return Object.values(res);
};
console.log(filter(strings));
I have an array like this:
var arr = [a,a,b,b,b,c]
The result(a new array) should only show all the values which are exactly 2 times in this array, e.g.: a
Do you guys know how I could realize this? Thanks
Please try this code:
var arr = ['a','a','b','b','b','c'];
var numberOfOccurrences = {};
arr.forEach(function (item) {
numberOfOccurrences[item] = (numberOfOccurrences[item] || 0) + 1;
});
var duplicates = Object.keys(numberOfOccurrences).filter(function (item) { return numberOfOccurrences[item] === 2 });
console.log(duplicates);
You can first create object and add properties with forEach loop and then use filter on Object.keys to return array as result.
var arr = ['a','a','b','b','b','c'];
var o = {}
arr.forEach(e => o[e] = (o[e] || 0) + 1);
var result = Object.keys(o).filter(e => o[e] == 2);
console.log(result)