Javascript remove duplicated object from array - javascript

i'm having trouble to remove duplicated object from my array
example:
var list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}, {place:"AAA",name:"Him"}];
in this example i have 3 objects, and i want to remove the object that have the duplicated place

Just in case someone wonders: underscore.js solution:
var list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}, {place:"AAA",name:"Him"}];
_.uniq(list, function(item, key, a) {
return item.place;
})
Example Fiddle

A simple one:
var list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}, {place:"AAA",name:"Him"}];
list.forEach(function(i) {
var duplicates = list.filter(function(j) {
return j !== i && j.place == i.place;
});
duplicates.forEach(function(d) { list.splice(list.indexOf(d), 1); });
});
// list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}];
document.write(JSON.stringify(list));

As you added:
i want to remove just one, dont matter wich one
If you want to remove duplicated items and keep only the first occcurence of particular place, you can simply use a simple loop to re-create a new array from the input:
var list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}, {place:"AAA",name:"Him"}];
var uniqPlace = function(array){
var result = [];
array.forEach(function(el){
if (result.filter(function(n){ return n.place === el.place }).length==0){
result.push(el);
}
})
return result;
}
Output:
uniqPlace(list);
[{"place":"AAA","name":"Me"},{"place":"BBB","name":"You"}]

Try this.
var result = {};
for (i = 0, n = arr.length; i < n; i++) {
var item = arr[i];
result[ item.place + " - " + item.name ] = item;
}
Loop the result again, and recreate the array.
i = 0;
for(var item in result) {
clearnArr[i++] = result[item];
}

Create a object to store the items by their place value, as the new item with the same key will overwrite the old one, this will easily remove all dulplicates.
var list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}, {place:"AAA",name:"Him"}];
var removeDuplicate = function(list) {
var keyStore = {};
var output = [];
// If you want to creata totally new one from old, use
// list = JSON.parse(JSON.stringify(list));
// The above commented out code will create a copy of list, so the items in output will not affect the original ones.
list.forEach(function(item) {
// new one overwrites old one.
keyStore[item.place] = item;
});
var key;
for (key in keyStore) {
output.push(keyStore[key]);
}
return output;
};
console.log(removeDuplicate(list));

3 way to remove duplicate objects from array
let list = [{place:"AAA",name:"Me"},
{place:"BBB",name:"You"},
{place:"AAA",name:"Him"}];
let output1 = Array.from(new Set(list.map(list=>list.place))).map(place=>{
return {
place: place,
name: list.find(a=>a.place===place).name
}
})
console.log('------------------------1st way')
console.log(output1)
let output2 = list.reduce((accumulator, element) => {
if (!accumulator.find(el => el['place'] === element['place'])) {
accumulator.push(element);
}
return accumulator;
},[]);
console.log('------------------------2nd way')
console.log(output2)
const output3 = [];
const map = new Map();
for (const object of list) {
if(!map.has(object.place)){
map.set(object.place, true);
output3.push({
place: object.place,
name: object.name
});
}
}
console.log('------------------------3rd way')
console.log(output3)

Related

How do I manipulate a value of an array in javascript?

I'm quite new to Javascript and I have the following javascript array in an AJAX Request that contains the following:
["12435|#CANON#DEVICE#|#50#|Machine Detail|Details|SampleRow|FALSE|FALSE|FALSE|FALSE|FALSE|FALSE|TRUE"]
I wanna manipulate the TRUE and FALSE value. If they're in uppercase, I want to make it lowercase. Any idea how I can do it?
If you want to modify the list you could just loop through all of its items, modify the value and set it to the same index of the list. (You don't need to set it if you are dealing with objects).
var list = ["12435|#CANON#DEVICE#|#50#|Machine Detail|Details|SampleRow|FALSE|FALSE|FALSE|FALSE|FALSE|FALSE|TRUE"];
list.forEach(function(item, index) {
list[index] = item.replace(/(TRUE|FALSE)/g, function(upperCase) {
return upperCase.toLowerCase();
});
});
console.log(list);
Same thing using a for loop:
var list = ["12435|#CANON#DEVICE#|#50#|Machine Detail|Details|SampleRow|FALSE|FALSE|FALSE|FALSE|FALSE|FALSE|TRUE"];
for (var index = 0; index < list.length; index++) {
list[index] = list[index].replace(/(TRUE|FALSE)/g, function(upperCase) {
return upperCase.toLowerCase();
});
}
console.log(list);
If you want to create a copy you could do:
var list = ["12435|#CANON#DEVICE#|#50#|Machine Detail|Details|SampleRow|FALSE|FALSE|FALSE|FALSE|FALSE|FALSE|TRUE"];
var newList = list.map(function(item) {
return item.replace(/(TRUE|FALSE)/g, function(upperCase) {
return upperCase.toLowerCase();
});
});
console.log(newList);
The above scripts will also transform something like ["THIS IS NOT TRUE|TRUE|FALSE"] to ["THIS IS NOT true|true|false"]. If you do not want that you should use this regex instead /(^|(?<=\|))(TRUE|FALSE)(\||$)/ i.e.:
var list = ["12435|#CANON#DEVICE#|#50#|Machine Detail|Details|SampleRowFALSE|FALSE|FALSE|FALSE|FALSE|FALSE|FALSE|TRUE"];
for (var index = 0; index < list.length; index++) {
list[index] = list[index].replace(/(^|(?<=\|))(TRUE|FALSE)(\||$)/g, function(upperCase) {
return upperCase.toLowerCase();
});
}
console.log(list);
Just use replace with map:
const arr = ["12435|#CANON#DEVICE#|#50#|Machine Detail|Details|SampleRow|FALSE|FALSE|FALSE|FALSE|FALSE|FALSE|TRUE"];
const res = arr.map(e => e.replace(/(TRUE|FALSE)/g, m => m.toLowerCase()));
console.log(res);
const arrayString = ["12435|#CANON#DEVICE#|#50#|Machine Detail|Details|SampleRow|FALSE|FALSE|FALSE|FALSE|FALSE|FALSE|TRUE"]
const arrayOfValues = arrayString[0].split('|').map(val => {
if(val === 'TRUE' || val === 'FALSE') {
return val.toLowerCase();
} else {
return val;
}
});
console.log(arrayOfValues)
Use RegEx as you have been told before.
If you want to learn more about this look at: W3Schools
One solution could be like this:
var ajaxResponse = "12435|#CANON#DEVICE#|#50#|Machine Detail|Details|SampleRow|FALSE|FALSE|FALSE|FALSE|FALSE|FALSE|TRUE";
ajaxResponse = ajaxResponse.replace(/FALSE/g, "false");
ajaxResponse = ajaxResponse.replace(/TRUE/g, "true");
console.log(ajaxResponse);

JQuery remove duplicate from array where string contains same text

I have an array with X number of items. Each has variables separated by a pipe character. In a loop I can split on the pipe to get the second item; but how do I splice to remove the duplicate.
"Sometext|22621086|address|333629dc87894a7ea7df5291fa6d1836|PC_E|1803"
"Sometext2|22622138|working|d3e70175ffe942568cd21f1cf96f4d63|PC_E|1803"
"Sometext3|22622138|working|851946e6325445da99c113951590f714|PC_E|1803"
Results should be this.
"Sometext|22621086|address|333629dc87894a7ea7df5291fa6d1836|PC_E|1803"
"Sometext2|22622138|working|d3e70175ffe942568cd21f1cf96f4d63|PC_E|1803"
Note that the duplicate 22622138 is a random number so the solution needs to work for any number in this location (it's always in the arr[1] position).
This is what I tried:
$.each(arr_transcript, function (i, e) {
if (e.length != 0) {
var arr = e.split("|")
var i = arr_transcript.indexOf(arr[1]);
if (i != -1) {
arr_transcript.splice(i, 1);
}
}
});
Here's a generic function:
function uniqBy(a, key) {
let seen = new Set();
return a.filter(item => {
let k = key(item);
return !seen.has(k) && seen.add(k);
});
};
var data = [
"Sometext|22621086|address|333629dc87894a7ea7df5291fa6d1836|PC_E|1803",
"Sometext2|22622138|working|d3e70175ffe942568cd21f1cf96f4d63|PC_E|1803",
"Sometext3|22622138|working|851946e6325445da99c113951590f714|PC_E|1803"
];
var result = uniqBy(data, item => item.split('|')[1]);
console.log(result)
See here for more info.
Create a map of the numbers you want to check against, and then filter based on that
var arr_transcript = [
"Sometext|22621086|address|333629dc87894a7ea7df5291fa6d1836|PC_E|1803",
"Sometext2|22622138|working|d3e70175ffe942568cd21f1cf96f4d63|PC_E|1803",
"Sometext3|22622138|working|851946e6325445da99c113951590f714|PC_E|1803"
];
var map = arr_transcript.map(function(text) {
return text.split('|')[1];
});
var filtered = arr_transcript.filter(function(item, index) {
return index === map.lastIndexOf( map[index] );
});
console.log(filtered)

push only unique elements in an array

I have array object(x) that stores json (key,value) objects. I need to make sure that x only takes json object with unique key. Below, example 'id' is the key, so i don't want to store other json objects with 'item1' key.
x = [{"id":"item1","val":"Items"},{"id":"item1","val":"Items"},{"id":"item1","val":"Items"}]
var clickId = // could be "item1", "item2"....
var found = $.inArray(clickId, x); //
if(found >=0)
{
x.splice(found,1);
}
else{
x.push(new Item(clickId, obj)); //push json object
}
would this accomplish what you're looking for? https://jsfiddle.net/gukv9arj/3/
x = [
{"id":"item1","val":"Items"},
{"id":"item1","val":"Items"},
{"id":"item2","val":"Items"}
];
var clickId = [];
var list = JSON.parse(x);
$.each(list, function(index, value){
if(clickId.indexOf(value.id) === -1){
clickId.push(value.id);
}
});
You can't use inArray() because you are searching for an object.
I'd recommend rewriting a custom find using Array.some() as follows.
var x = [{"id":"item1","val":"Items"},{"id":"item1","val":"Items"},{"id":"item1","val":"Items"}]
var clickId = "item1";
var found = x.some(function(value) {
return value.id === clickId;
});
alert(found);
Almost 6 years later i ended up in this question, but i needed to fill a bit more complex array, with objects. So i needed to add something like this.
var values = [
{value: "value1", selected: false},
{value: "value2", selected: false}
//there cannot be another object with value = "value1" within the collection.
]
So I was looking for the value data not to be repeated (in an object's array), rather than just the value in a string's array, as required in this question. This is not the first time i think in doing something like this in some JS code.
So i did the following:
let valueIndex = {};
let values = []
//I had the source data in some other and more complex array.
for (const index in assetsArray)
{
const element = assetsArray[index];
if (!valueIndex[element.value])
{
valueIndex[element.value] = true;
values.push({
value: element.value,
selected: false
});
}
}
I just use another object as an index, so the properties in an object will never be repated. This code is quite easy to read and surely is compatible with any browser. Maybe someone comes with something better. You are welcome to share!
Hopes this helps someone else.
JS objects are great tools to use for tracking unique items. If you start with an empty object, you can incrementally add keys/values. If the object already has a key for a given item, you can set it to some known value that is use used to indicate a non-unique item.
You could then loop over the object and push the unique items to an array.
var itemsObj = {};
var itemsList = [];
x = [{"id":"item1","val":"foo"},
{"id":"item2","val":"bar"},
{"id":"item1","val":"baz"},
{"id":"item1","val":"bez"}];
for (var i = 0; i < x.length; i++) {
var item = x[i];
if (itemsObj[item.id]) {
itemsObj[item.id] = "dupe";
}
else {
itemsObj[item.id] = item;
}
}
for (var myKey in itemsObj) {
if (itemsObj[myKey] !== "dupe") {
itemsList.push(itemsObj[myKey]);
}
}
console.log(itemsList);
See a working example here: https://jsbin.com/qucuso
If you want a list of items that contain only the first instance of an id, you can do this:
var itemsObj = {};
var itemsList = [];
x = [{"id":"item1","val":"foo"},
{"id":"item2","val":"bar"},
{"id":"item1","val":"baz"},
{"id":"item1","val":"bez"}];
for (var i = 0; i < x.length; i++) {
var item = x[i];
if (!itemsObj[item.id]) {
itemsObj[item.id] = item;
itemsList.push(item);
}
}
console.log(itemsList);
This is late but I did something like the following:
let MyArray = [];
MyArray._PushAndRejectDuplicate = function(el) {
if (this.indexOf(el) == -1) this.push(el)
else return;
}
MyArray._PushAndRejectDuplicate(1); // [1]
MyArray._PushAndRejectDuplicate(2); // [1,2]
MyArray._PushAndRejectDuplicate(1); // [1,2]
This is how I would do it in pure javascript.
var x = [{"id":"item1","val":"Items"},{"id":"item1","val":"Items"},{"id":"item1","val":"Items"}];
function unique(arr, comparator) {
var uniqueArr = [];
for (var i in arr) {
var found = false;
for (var j in uniqueArr) {
if (comparator instanceof Function) {
if (comparator.call(null, arr[i], uniqueArr[j])) {
found = true;
break;
}
} else {
if (arr[i] == uniqueArr[j]) {
found = true;
break;
}
}
}
if (!found) {
uniqueArr.push(arr[i]);
}
}
return uniqueArr;
};
u = unique(x, function(a,b){ return a.id == b.id; });
console.log(u);
y = [ 1,1,2,3,4,5,5,6,1];
console.log(unique(y));
Create a very readable solution with lodash.
x = _.unionBy(x, [new Item(clickId, obj)], 'id');
let x = [{id:item1,data:value},{id:item2,data:value},{id:item3,data:value}]
let newEle = {id:newItem,data:value}
let prev = x.filter(ele=>{if(ele.id!=new.id)return ele);
newArr = [...prev,newEle]

Associative array was sorting indexs if it return from regexp

I need to save order in array. A normal array was destroying it, so i found associative array, but with indexes from regexp was sorting records too.
My function is
var myArray = {};
var searchIndex = '';
$("#searchList").find('li').each(function( index ) {
id = $( this ).attr('id');
if(id.match(/search(:?\d+|\w+)/)){
searchIndex = id.match(/search(\d+|\w+)/)[1];
myArray[searchIndex] = "empty";
}
});
This code works well, order are saved.
myArray[id] = "empty";
http://screenshooter.net/100008827/fhbsvjm
But when i want to remove string "search" from id, by regexp, array just sorting indexes...
searchIndex = id.match(/search(\d+|\w+)/)[1];
myArray[searchIndex] = "empty";
http://screenshooter.net/100008827/gmxusyu
But order should be last->7->9->8
JavaScript does not have associative arrays. The plain objects in JavaScript are similar to associative arrays in some ways, but the order of their properties is not guaranteed.
If you want an associative array that preserves the order of items in the order they were added, it is possible to create one from scratch. Here is a fairly simple implementation that provides that functionality:
function AssociativeArray() {
var items = [];
var refs = {};
this.set = function(key, value) {
if (key in refs) {
refs[key].value = value;
} else {
var entry = { key: key, value: value };
items.push(entry);
refs[key] = entry;
}
};
this.get = function(key) {
var entry = refs[key];
return entry && entry.value;
};
this.allItems = function() {
return items.slice();
};
}
var assoc = new AssociativeArray();
assoc.set(7, "hello");
assoc.set(3, "goodbye");
assoc.set("cheer", "yay");
var items = assoc.allItems();
for (var i = 0; i < items.length; i += 1) {
console.log(items[i].key + " - " + items[i].value);
}
console.log("The item with key 7 is: " + assoc.get(7));
The way you would adapt this to your current code is:
var myArray = new AssociativeArray();
$("#searchList").find('li').each(function( index ) {
var id = $( this ).attr('id'),
searchIndex;
if(id.match(/search(:?\d+|\w+)/)){
searchIndex = id.match(/search(\d+|\w+)/)[1];
myArray.set(searchIndex, "empty");
}
});
The first code snippet above shows how to iterate through the array in the order that items were added.

Filter Array on same name and date

var Array = [{"Name":"Temp","Date":"2014-10-23"},
{"Name":"Temp","Date":"2014-10-22"},
{"Name":"Temp","Date":"2014-10-18"},
{"Name":"Temp","Date":"2014-10-19"},
{"Name":"Temp2","Date":"2014-10-12"},
{"Name":"Temp2","Date":"2014-06-12"}]
What would be the best way to filter the above array on the following condition.
*If the name is the same, then filter away all the objects with the same name and leave only the object with the latest date left.
All I can think of is to do for loops. Note that Date is a real dateObject and not a string as I have wrote above which means that you can do Date comparisons.
Using Array.reduce(), i was able to get it down to an object containing only Temp and Temp2 with their dates:
var obj = array.reduce(function(base,cur){
if (base[cur.Name]) {
if (base[cur.Name].Date < cur.Date) {
base[cur.Name].Date = cur.Date;
} else {
return base;
}
} else {
base[cur.Name] = cur;
return base;
}
},{});
From there, you can just get the object's values with Object.keys().map():
array = Object.keys(obj).map(function(k){
return obj[k];
});
var array = [{"Name":"Temp","Date":new Date("2014-10-23")},
{"Name":"Temp","Date":new Date("2014-10-22")},
{"Name":"Temp","Date":new Date("2014-10-18")},
{"Name":"Temp","Date":new Date("2014-10-19")},
{"Name":"Temp2","Date":new Date("2014-10-12")},
{"Name":"Temp2","Date":new Date("2014-06-12")}];
var obj = {};
for(var i in array){
if(!obj[array[i].Name] || obj[array[i].Name].getTime() < array[i].Date.getTime())
obj[array[i].Name] = array[i].Date;
}
then if you need it to be an array of objects:
array = [];
for(var name in obj){
array.push({Name: name, Date: obj[name]});
}
var Array = [{"Name":"Temp","Date":"2014-10-23"},
{"Name":"Temp","Date":"2014-10-22"},
{"Name":"Temp","Date":"2014-10-18"},
{"Name":"Temp","Date":"2014-10-19"},
{"Name":"Temp2","Date":"2014-10-12"},
{"Name":"Temp2","Date":"2014-06-12"}]
var result = {};
Array.forEach(function(item) {
var name = item['Name'];
if(result[name]) {
result[name].push(item['Date']);
} else {
result[name] = [item['Date']];
}
})
Object.keys(result).forEach(function(item) {
result[item] = Math.max.apply(null, result[item]);
})
aggragate the array by name to {Name: 'Temp', Date: ['2014-10-23', '2013-10-32', 'xxxx']}
then get the max date by Math.max.apply
Here you go, Works perfect for any random orders
var Array = [{"Name":"Temp","Date":"2014-10-03"},
{"Name":"Temp","Date":"2014-10-22"},
{"Name":"Temp","Date":"2014-10-18"},
{"Name":"Temp","Date":"2014-10-19"},
{"Name":"Temp2","Date":"2014-10-12"},
{"Name":"Temp2","Date":"2014-06-12"}];
var tempArray = []; //This array will hold your Result Set
var tempArrayName = [];
var tempDate = {};
$.each(Array, function(i, v) {
if(tempArrayName.indexOf(Array[i].Name) < 0){
tempArray.push({ "Name":Array[i].Name,"Date":Array[i].Date});
tempArrayName.push(Array[i].Name);
tempDate[Array[i].Name] = Array[i].Date;
}else{
if( new Date((Array[i].Date))> new Date(tempDate[Array[i].Name])){
$.each(tempArray, function(j, k) {
if(tempArray[j].Name == Array[i].Name){
tempArray[j].Date = Array[i].Date;
}
});
}
}
});
console.log(tempArray);
I'd advise against overwriting the Array object. Anyhow,
one way would be to group the dates using an object:
var data = [
{"Name":"Temp","Date": new Date("2014-10-23")},
{"Name":"Temp","Date": new Date("2014-10-22")},
{"Name":"Temp","Date": new Date("2014-10-18")},
{"Name":"Temp","Date": new Date("2014-10-19")},
{"Name":"Temp2","Date": new Date("2014-10-12")},
{"Name":"Temp2","Date": new Date("2014-06-12")}
];
var name2dates = Object.create(null);
data.forEach(function(thing){
if(!name2dates[thing.Name]){
name2dates[thing.Name] = thing.Date;
}else{
name2dates[thing.Name] = thing.Date > name2dates[thing.Name] ?
thing.Date : name2dates[thing.Name];
}
});
And to create a 'filtered' array from this, if that's what you
need, then:
Object.keys(name2dates).map(function(name){
return {Name: name, Date: name2dates[name]};
});
Is this helpful?
$.grep(Array, function(v) {
return v.Name === "Temp";
}).reduce(function (a, b) { return a.Date > b.Date ? a : b; });

Categories