I am trying to remove duplicate JSON Objects from the array in ServiceNow.
Tried below code but it does not remove the duplicate. I want to compare both name & city.
var arr1 = '[{"name":"Pune","city":"India"},{"name":"Pune","city":"India"}]';
var splitlen = JSON.parse(arr1);
alert(splitlen.length);
var uniqueArray = [];
var uniqueJson = {};
for(i=0;i<splitlen.length;i++)
{
if(uniqueArray.indexOf(splitlen[i].name)==-1)
{
uniqueArray.push(splitlen[i]);
}
}
alert(JSON.stringify(uniqueArray));
Expected output :
[{"name":"Pune","city":"India"}]
uniqueArray.indexOf doesn't work because you're comparing objects against strings (splitlen[i].name). Try to use .find() instead:
var arr1 = '[{"name":"Pune","city":"India"},{"name":"Pune","city":"India"}]';
var splitlen = JSON.parse(arr1);
var uniqueArray = [];
var uniqueJson = {};
for(i=0;i<splitlen.length;i++)
{
if(!uniqueArray.find(x => x.name === splitlen[i].name))
{
uniqueArray.push(splitlen[i]);
}
}
console.log(uniqueArray);
or
var arr1 = '[{"name":"Pune","city":"India"},{"name":"Pune","city":"India"}]';
var splitlen = JSON.parse(arr1);
function compare(x){
return x.name === splitlen[i].name;
}
var uniqueArray = [];
var uniqueJson = {};
for(i=0;i<splitlen.length;i++)
{
if(!uniqueArray.find(compare))
{
uniqueArray.push(splitlen[i]);
}
}
console.log(uniqueArray);
you can try this. Also one more thing your array declaration is not right, remove single quotes from array.
var arr1 = [{"name":"Pune","city":"India"},{"name":"Pune","city":"India"}];
function getUniqueListByKey(arr, key) {
return [...new Map(arr.map(item => [item[key], item])).values()]
}
var arr2 = getUniqueListByKey(arr1, "name")
console.log(arr2);
Please try the following example
const arr1 = '[{"name":"Pune","city":"India"},{"name":"Pune","city":"India"}]';
const splitlen = JSON.parse(arr1);
const output = splitlen.reduce((previousValue, currentValue) => {
const { name, city } = currentValue;
const index = previousValue.findIndex(
(entry) => entry.name === name && entry.city === city
);
if (index === -1) {
return [...previousValue, currentValue];
}
return previousValue;
}, []);
console.log(output);
See
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
Put the records in a hashset. If there is collision in the hashset, there is duplicate. This approach is O(n) while comparing all pairs is $O(n^2)$.
I'm trying to get an answer, here's my idea:
Create a function to compare two objects then create a function to get the unique value
function isEquals(obj1, obj2) {
const aProps = Object.getOwnPropertyNames(obj1);
const bProps = Object.getOwnPropertyNames(obj2);
if (aProps.length !== bProps.length) {
return false;
}
for (let j = 0; j < aProps.length; j++) {
const propName = aProps[j];
if (JSON.stringify(obj1[propName]) !== JSON.stringify(obj2[propName])) {
return false;
}
} return true;
}
function getUnique(arr) {
var uniqueArray = [];
for (var item of arr) {
const uniqueItems = arr.filter(i => isEquals(item, i));
if (uniqueItems.length !== 0) {
uniqueArray.push(Object.assign({}, uniqueItems.shift()));
}
arr = arr.filter(i => !isEquals(item, i));
}
return uniqueArray;
}
Hope it helps!
Related
let array=[1,1,2,3,4,4,5,5,6,6,7,8]:
I want to get 2 array of unique and duplicate elements: duplicate element's array1:[1,4,5,6] unique element's array2:[2,3,7,8]
Help is very much appreciated.
Simply use a map to filter out duplicates. Here's a working solution.
let arr= [1,1,2,3,4,4,5,5,6,6,7,8];
function uniqueAndDuplicates() {
var obj = {};
var duplicates = [];
var noDup = [];
for(var i = 0; i < arr.length; i++){
if(!obj[arr[i]]){
obj[arr[i]] = 1;
noDup.push(arr[i]);
} else {
duplicates.push(arr[i]);
}
}
var unique = noDup.filter(function(item, index){
if(!duplicates.includes(noDup[index])){
return noDup[index];
}
});
return {
unique,
duplicates
}
}
console.log(uniqueAndDuplicates(arr));
One solution is you can create a freq map and then you can essentially create an Array from that map then filter out the counts greater than 1 and less than 1.
let array=[1,1,2,3,4,4,5,5,6,6,7,8]
const returnUniqueAndDuplicateElements = (arr) => {
let freqMap = {};
for(const idx in arr){
let number = arr[idx];
if(!freqMap[number]){
freqMap[number]=0;
}
freqMap[number]++;
}
const entries = Object.entries(freqMap);
return {
unique: entries.filter(([, freq]) => freq <= 1).map(item => Number(item[0])),
duplicates: entries.filter(([, freq]) => freq > 1).map(item => Number(item[0]))
}
}
console.log(returnUniqueAndDuplicateElements(array))
I am adding my solution since there is none with JS sets[?] just yet:
function uniqueAndDuplicate(arrayOfNumbers) {
const unique = new Set();
const duplicate = new Set();
arrayOfNumbers.forEach((elem) => {
if (unique.has(elem)) {
unique.delete(elem);
duplicate.add(elem);
} else if (!duplicate.has(elem)) {
unique.add(elem);
}
});
return {
unique: [...unique],
duplicate: [...duplicate],
};
}
console.log(uniqueAndDuplicate([1,1,2,3,4,4,5,5,6,6,7,8]));
Hello this is my array;
arr =[{cNo:1,buyOrSel:'A',ip:192.168.1.1},{cNo:1,buyOrSel:'S',ip:192.168.1.1},{cNo:2,buyOrSel:'S',ip:192.168.1.2},{cNo:3,buyOrSel:'A',ip:192.168.1.1},{cNo:4,buyOrSel:'S',ip:192.168.1.3},{cNo:5,buyOrSel:'S',ip:192.168.1.2}]
I want to group in Object like this;
[{cNo:'1,3',ip:192.168.1.1},{cNo:'2,5',ip:192.168.1.2}]
I don't want to use nested For loop.What is the best way for this ?
let arr = [{cNo:1,buyOrSel:'A',ip:"192.168.1.1"},{cNo:1,buyOrSel:'S',ip:"192.168.1.1"},{cNo:2,buyOrSel:'S',ip:"192.168.1.2"},{cNo:3,buyOrSel:'A',ip:"192.168.1.1"},{cNo:4,buyOrSel:'S',ip:"192.168.1.3"},{cNo:5,buyOrSel:'S',ip:"192.168.1.2"}];
arr = arr.reduce((prev, a) => {
let cNo = prev[a.ip] = prev[a.ip] || [];
if (cNo.indexOf(a.cNo) < 0) {
prev[a.ip].push(a.cNo);
};
return prev
}, {});
arr = Object.keys(arr).map(key => {
return {
cNo: arr[key].join(),
ip: key
}
});
console.log(arr);
you can use object for better grouping.
and instead of pushing only cNo, you can push whole object too.
let arr = [{cNo:1,buyOrSel:'A',ip:"192.168.1.1"},{cNo:1,buyOrSel:'S',ip:"192.168.1.1"},{cNo:2,buyOrSel:'S',ip:"192.168.1.2"},{cNo:3,buyOrSel:'A',ip:"192.168.1.1"},{cNo:4,buyOrSel:'S',ip:"192.168.1.3"},{cNo:5,buyOrSel:'S',ip:"192.168.1.2"}];
let objectByIP = {};
arr.forEach(element => {
if (!objectByIP[element.ip]) {
objectByIP[element.ip] = [element.cNo];
} else {
objectByIP[element.ip].push(element.cNo);
}
});
console.log(objectByIP);
console.log(Object.keys(objectByIP));
you can use map():
let a = arr.map(a=>{ return {cNo: a.cNo, ip: a.ip}})
Here is my requirement. I was able to achieve to some level in java but we need to move it to typescript (client side).
Note: The below input is for example purpose and may vary dynamically.
Input
var input = ["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"];
We need to create an utility function that takes above input and returns output as below.
Output:
Should be string not an object or anything else.
"{ a { name, type }, b { city {name, zip } , desc }, c }"
any help is much appreciated.
I don't see that typescript plays any role in your question, but here's a solution for constructing the string you requested. I first turn the array into an object with those properties, then have a function which can turn an object into a string formatted like you have
const input = ["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"];
const arrayToObject = (arr) => {
return arr.reduce((result, val) => {
const path = val.split('.');
let obj = result;
path.forEach(key => {
obj[key] = obj[key] || {};
obj = obj[key];
});
return result;
}, {});
}
const objectToString = (obj, name = '') => {
const keys = Object.keys(obj);
if (keys.length === 0) {
return name;
}
return `${name} { ${keys.map(k => objectToString(obj[k], k)).join(', ')} }`;
}
const arrayToString = arr => objectToString(arrayToObject(arr));
console.log(arrayToString(input));
Here's another variation. Trick is to parse the strings recursively and store the intermediate results in an Object.
function dotStringToObject(remainder, parent) {
if (remainder.indexOf('.') === -1) {
return parent[remainder] = true
} else {
var subs = remainder.split('.');
dotStringToObject(subs.slice(1).join('.'), (parent[subs[0]] || (parent[subs[0]] = {})))
}
}
var output = {};
["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"].forEach(function(entry) {
dotStringToObject(entry, output)
});
var res = JSON.stringify(output).replace(/\"/gi, ' ').replace(/\:|true/gi, '').replace(/\s,\s/gi, ', ');
console.log(res)
// Prints: { a { name, type }, b { city { name, zip }, desc }, c }
You could do something like this:
var input = ["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"];
var output = {};
for(var i =0; i < input.length; i+=2){
output[String.fromCharCode(i+97)] = {};
output[String.fromCharCode(i+97)].name = input[i];
output[String.fromCharCode(i+97)].type = input[i+1];
}
console.log(JSON.stringify(output));
Trying to find an algorithm that will do the following:
let input = [ 'kooty', 'dlnnoo', 'emor', 'dlnnoo', 'kooty', 'aiprs' ]
function combine(input){
// you should return
[ ['kooty', 'kooty'], ['dlnnoo','dlnnoo'], ['emor'], ['aiprs'] ]
}
I got the answer by using Lodash but i was wondering if there was a way without
function combine(input){
let sortedCity = [];
let finalArr = [];
for(let city in input){
sortedCity.push(input[city].toLowerCase().split('').sort().join(''));
}
let a = lodash.groupBy(sortedCity)
return Object.values(a)
}
combine(input)
let input = [ 'kooty', 'dlnnoo', 'emor', 'dlnnoo', 'kooty', 'aiprs' ]
function combine (input) {
let sorted = input.map(cur => cur.toLowerCase().split('').sort().join(''))
let cache = {} // cache value to index of result array
return sorted.reduce((sum, cur) => {
let index = cache[cur]
if (index !== undefined) {
sum[index].push(cur)
} else {
sum.push([cur])
cache[cur] = sum.length - 1
}
return sum
}, [])
}
combine(input)
im trying to remove adjacent duplicates but instead of desired result (3 results) i'm getting only 2 results
my Expected Output:
[{"mw://HOME_BIN":{"position":0}},{"mw://diagnosis_HOME":{"position":3}},{"mw://HOME_BIN":{"position":3}}]
here is what i have tried:
var arr = [{"mw://HOME_BIN":{"position":0}},{"mw://diagnosis_HOME":{"position":3}},{"mw://HOME_BIN":{"position":3}},{"mw://HOME_BIN":{"position":3}}];
var nArr = [];
for(var i = 0; i < arr.length;++i){
var key1 = Object.keys(arr[i]).join('');
var nLength = ((i + 1) > arr.length - 1 ) ? 0 : i + 1;
var key2 = Object.keys(arr[nLength]).join('');
if(key1 == key2) continue;
nArr.push(arr[i]);
}
console.log(nArr);
from the above result you can see one more element is missing
Easier to use filter:
var arr = [{"mw://HOME_BIN":{"position":0}},{"mw://diagnosis_HOME":{"position":3}},{"mw://HOME_BIN":{"position":3}},{"mw://HOME_BIN":{"position":3}}];
let lastKey;
const filtered = arr.filter((item) => {
const key = Object.keys(item)[0];
if (key === lastKey) return false;
lastKey = key;
return true;
});
console.log(filtered);
If you're looking for adjacent keys, you should just track the latest key, and not compare all of them.
var arr = [{"mw://HOME_BIN":{"position":0}},{"mw://diagnosis_HOME":{"position":3}},{"mw://HOME_BIN":{"position":3}},{"mw://HOME_BIN":{"position":3}}];
let result = [], prev_key = '', key;
for(let item of arr) {
key = Object.keys(item).sort().join();
if(key == prev_key) continue;
prev_key = key;
result.push(item);
}
console.log(result);
var arr =
[
{"mw://HOME_BIN":{"position":0}},
{"mw://diagnosis_HOME":{"position":3}},
{"mw://HOME_BIN":{"position":3}},
{"mw://HOME_BIN":{"position":3}}
];
var nArr = [];
arr.forEach((ar,index) => {
if(index === arr.length - 1) {
nArr.push(ar);
return;
}
if(JSON.stringify(ar) !== JSON.stringify(arr[index+1])){
nArr.push(ar);
}
})
console.log(nArr);
You can use JSON.stringify to compare whole objects instead of using single key, for your scalability