How can I remove duplication from list - javascript

I have this kind of list from my web service. I want to eliminate username duplication:
Mylist = [{
"username": "Plr1",
"is_online": true,
"email": null,
"message": null,
"direction": 1,
"image_url": ""
}, {
"username": "plr2",
"is_online": false,
"email": "",
"message": null,
"direction": 1,
"image_url": ""
}, {
"username": "plr1",
"is_online": false,
"email": "",
"message": null,
"direction": 1,
"image_url": null
}];
Is there a function that allows me to remove duplicated values (one of elements=Plr1)?

You can use Array.filter
var Mylist = [{"username":"Plr1","is_online":true,"email":null,"message":null,"direction":1,"image_url":""},{"username":"plr2","is_online":false,"email":"","message":null,"direction":1,"image_url":""},{"username":"plr1","is_online":false,"email":"","message":null,"direction":1,"image_url":null} ];
var keys = [];
var newList = Mylist.filter(
function(x){
var val = x.username.toLowerCase();
if (!keys[val]) {
keys[val] = true;
return true;
}
return false;
}
);
keys = null;
console.log(newList);
It will not work in older browsers out of the box. If you look at the link I posted to above, there is a pollyfill to make them work.

DEMO: http://jsfiddle.net/abc123/ZgYbB/
NOTE: The last for loop is just to show that items were removed and what is left in the array.
JS:
var Mylist= [{"username":"Plr1","is_online":true,"email":null,"message":null,"direction":1,"image_url":""},{"username":"plr2","is_online":false,"email":"","message":null,"direction":1,"image_url":""},{"username":"plr1","is_online":false,"email":"","message":null,"direction":1,"image_url":null} ];
for (var i = 0; i < Mylist.length; i++) {
for(var j = i + 1; j < Mylist.length; j++) {
if(Mylist[i].username.toLowerCase() == Mylist[j].username.toLowerCase())
Mylist.splice(j, 1);
}
}
//Not needed just proof that items were removed.
for (var i = 0; i < Mylist.length; i++) {
alert(Mylist[i].username);
}

This will do what you want (assuming you're looking for case-insensitive comparison of usernames).
EDIT to add Demo: http://jsfiddle.net/vBZhR/
var Mylist= [{"username":"Plr1","is_online":true,"email":null,"message":null,"direction":1,"image_url":""},{"username":"plr2","is_online":false,"email":"","message":null,"direction":1,"image_url":""},{"username":"plr1","is_online":false,"email":"","message":null,"direction":1,"image_url":null} ];
dedupe(Mylist);
function dedupe(list) {
var usernames = {};
for (var i in list) {
if (usernames[list[i].username.toLowerCase()]) {
list.splice(i, 1);
} else {
usernames[list[i].username.toLowerCase()] = true;
}
}
return list;
}

Related

Is there a quick way to add to a JSON the elements of another similar JSON?

I want to use a location-based API for putting markers on a map project. This API returns a JSON containing data about the 50 closest scooters of a GET-provided location.
I want to combine the results of several of these JSONs, into one that would contain all the data of the scooters in a greater area (if possible without duplicates)
I already tried JSON1.concat(JSON2); without much success, as you can see in the code below.
var latitudes = makeArr(48.810067,48.900169,30);
var longitudes = makeArr(2.248876,2.42397,30);
var allskoots= new Array();
for (var i = 0; i < latitudes.length; i++) {
for (var j = 0; j < longitudes.length; j++) {
var req = new XMLHttpRequest();
req.open("GET", "https://api-prod.ibyke.io/v2/boards?latitude="+latitudes[i]+"&longitude="+longitudes[j]);
req.responseType = 'json';
req.send();
req.onload = function() {
var allscoots=allscoots.concat(req.response);
}
}
}
A single API answer looks like this :
{"result":0,
"items":[{"param1":value1_0,
"param2":value2_0},
{"param1":value1_1,
"param2":value2_1}
...
]
}
So I'd want to be able to get from 2 of these JSONs, for instance:
{"result":0,
"items":[{"param1":value1_0,
"param2":value2_0},
{"param1":value1_1,
"param2":value2_1}
]
}
and
{"result":0,
"items":[{"param1":value1_1,
"param2":value2_1},
{"param1":value1_2,
"param2":value2_2}
]
}
the following result :
{"result":0,
"items":[{"param1":value1_0,
"param2":value2_0},
{"param1":value1_1,
"param2":value2_1}
{"param1":value1_2,
"param2":value2_2}
]
}
Is there a simple way to do it in Javascript ?
Rudimentary answer and could be optimized, but is this what you are looking for?
var r1 = {
"result": 0,
"items": [{
"param1": "value1_0",
"param2": "value2_0"
},
{
"param1": "value1_1",
"param2": "value2_1"
}
]
}
var r2 = {
"result": 0,
"items": [{
"param1": "value1_1",
"param2": "value2_1"
},
{
"param1": "value1_2",
"param2": "value2_2"
}
]
}
var merged = {
"result": 0,
"items": r1.items.concat(r2.items.filter(x => !contains(r1.items, x)))
}
// assuming no duplicates in r2.items
/*
// in case of duplicates
merged.items = r1.items;
for (var i in r2.items) {
if (!contains(merged.items, r2.items[i]))
merged.items.push(r2.items[i]);
}
*/
console.log(merged);
function contains(array, elem) {
for (var i in array) {
if (isEquivalent(array[i], elem)) return true;
}
return false
}
// credit to http://adripofjavascript.com/blog/drips/object-equality-in-javascript.html
function isEquivalent(a, b) {
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
if (aProps.length != bProps.length) {
return false;
}
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
if (a[propName] !== b[propName]) {
return false;
}
}
return true;
}
Solve your JSON. Run my script. Hope you get it.
var r1 = {
"result": 0,
"items": [{
"param1": "value1_0",
"param2": "value2_0"
},
{
"param1": "value1_1",
"param2": "value2_1"
}
]
}
var r2 = {
"result": 0,
"items": [{
"param1": "value1_1",
"param2": "value2_1"
},
{
"param1": "value1_2",
"param2": "value2_2"
}
]
}
var final_arr = {"result": 0,"items": []};
final_arr.items.push(r1.items);
final_arr.items.push(r2.items);
console.log(final_arr);

how do not push all the array not have this product

for example i have this code i used this json:
"food": {
"appetizers": [
{
"id": 1,
"image": "../image/calammari.png",
"title": "rings",
"price": 11500,
"ingredient":[{
"id" : "0001",
"name": "avocado"
},
{
"id" : "0001",
"name": "tomato"
}
]
},
{
"id": 2,
"image": "../image/food2.png",
"title": "bang bang",
"price": 10000,
"ingredient":[{
"id" : "0001",
"name": "eggplant"
},
{
"id" : "0001",
"name": "cucumber"
}
]
}
from this json file if the array my access equal tomato , just i want to display the food that have tomato.
so i used this html:
<div ng-repeat="appetizer in appetizers ">
<div>
<img ng-src="{{appetizer.image}}" />
<div >
<p >
{{appetizer.title | uppercase}}
</p>
</div>
and this javascript :
var myAccess = ["tomato"];
$scope.test = [];
var appetizer = $scope.appetizers;
for (var i = 0; i < $scope.appetizers.length; i++) {
for (var j = 0; j < $scope.appetizers[i].ingredient.length; j++) {
if ($scope.appetizers[i].ingredient[j].name === myAccess) {
// what should i write here
}
}
}
return null; }
sorry its about this if someone can help please !!
so myAccess = tomato , and should read the first of the appetizer that in the ingredient tomato , and i want to push just the ingredient that have tomato .
You can use filter and some or every in the following way:
Items that have some of the ingredients
const data = [{"id":1,"image":"../image/calammari.png","title":"rings","price":11500,"ingredient":[{"id":"0001","name":"avocado"},{"id":"0001","name":"tomato"}]},{"id":2,"image":"../image/food2.png","title":"bang bang","price":10000,"ingredient":[{"id":"0001","name":"eggplant"},{"id":"0001","name":"cucumber"}]}];
const myAccess = ['avocado', 'tomato'];
console.log(
data.filter(
(item) =>
item.ingredient.some(
(ingredient) => myAccess.includes(ingredient.name)
)
)
);
Items that have all of the ingredients:
data.filter(
(item) =>
myAccess.every(
(ingredient)=>
item.ingredient.some(
(i)=>i.name===ingredient
)
)
);
it could be helpful for you
var app=angular.module("myapp",[]);
app.controller("test_ctrl",function($scope){
$scope.appetizers = [];
$scope.temp={
"food": {
"appetizers": [
{
"id": 1,
"image": "../image/calammari.png",
"title": "rings",
"price": 11500,
"ingredient":[
{
"id" : "0001",
"name": "avocado"
},
{
"id" : "0001",
"name": "tomato"
}
]
},
{
"id": 2,
"image": "../image/food2.png",
"title": "bang bang",
"price": 10000,
"ingredient":[
{
"id" : "0001",
"name": "eggplant"
},
{
"id" : "0001",
"name": "cucumber"
}
]
}
]
}
}
var myAccess = ["tomato"];
var appetizer = $scope.temp.food.appetizers;
for (var i = 0; i < appetizer.length; i++) {
for (var j = 0; j < appetizer[i].ingredient.length; j++) {
if (appetizer[i].ingredient[j].name === myAccess[0]) {
$scope.appetizers.push(appetizer[i]);
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="myapp" ng-controller="test_ctrl">
<div ng-repeat="appetizer in appetizers ">
<div>
<img ng-src="{{appetizer.image}}" />
<div >
<p >
{{appetizer.title | uppercase}}
</p>
</div>
</div>
</div>
In addition to the comment, check the below JS that might sort out your problem.
function myFunction() {
var myAccess = "tomato";
$scope.test = [];
var appetizer = $scope.appetizers;
for (var i = 0; i < $scope.appetizers.length; i++) {
var flag = 'false';
for (var j = 0; j < $scope.appetizers[i].ingredient.length; j++) {
if ($scope.appetizers[i].ingredient[j].name === myAccess) {
flag = 'true'; // Flag to check whether it's exist
break;
}
}
if(flag == 'false') {
appetizer.splice(index, i); // Pop that item if it's not exist
}
}
$scope.appetizers = appetizer; // Re-assign
}
Introduced variable flag that'll tell whether that array contains myAccess value or not. Based on that, I removed that index from that array variable appetizer. Finally, this array variable will replace scope variable.
I haven't checked the code. So, Just try or implement from yours using this logic if it suits.
EDIT - My code looks not much effective while comparing #HMR answer :)
Push appetizers into your array like this.
function myFunction() {
var myAccess = ["tomato"];
$scope.test = [];
var appetizer = $scope.appetizers;
for (var i = 0; i < appetizer.length; i++) {
for (var j = 0; j < appetizer[i].ingredient.length; j++) {
if (appetizer[i].ingredient[j].name === myAccess) {
// what should i write here
$scope.appetizers.push(appetizer[i]); // additional code here.
}
}
}
return null; }

compare two different arrays in javascript

can any one help in this i am trying to compare two different arrays for pushing values when comparision is equal. below are my two(imageslide.therapy),totalValues arrays and i want compare names like cats and dogs. if condition is true then i need to push their images urls.
var imageslide = {
"therapy": [
{
"name": "cats",
"images": [
{ "url": "cat/firstimg.jpg" },
{ "url": "cat/secondimg.jpg" },
{ "url": "cat/thirdimg.jpg" },
{ "url": "cat/fourthimg.jpg" }
]
},
{
"name": "dogs",
"images": [
{ "url": "dog/firstdog.jpeg" },
{ "url": "dog/seconddog.jpg" },
{ "url": "dog/thirddog.jpg" },
{ "url": "dog/fourthdog.jpg" }
]
},
]
}
var totalValues = ["cats","dogs"];
and i tried like below
var imageArray = imageslide.therapy
function compare(imageArray,totalValues ){
imageArray.forEach((e1)=>totalValues.forEach((e2)=>{
if(e1.name==e2){
console.log(e1.name,",",e2)
}
})
For what I understand from your question here is the answer. Please forgive me I don't know much about arrow function so I wrote it in simple javascript.
var imageslide = {
"therapy": [
{
"name": "cats",
"images": [
{ "url": "cat/firstimg.jpg" },
{ "url": "cat/secondimg.jpg" },
{ "url": "cat/thirdimg.jpg" },
{ "url": "cat/fourthimg.jpg" }
]
},
{
"name": "dogs",
"images": [
{ "url": "dog/firstdog.jpeg" },
{ "url": "dog/seconddog.jpg" },
{ "url": "dog/thirddog.jpg" },
{ "url": "dog/fourthdog.jpg" }
]
},
]
}
var totalValues = ["cats","dogs"];
var imageArray = imageslide.therapy
function compare(imageArray,totalValues ){
for(var i=0;i<imageArray.length;i++){
for(var j=0;j<totalValues.length;j++){
if(totalValues[j]=imageArray[i].name){
console.log(imageArray[i].name+"=="+totalValues[j]);
//imageArray[i].images.push({"url": "https://hexasoft.io"});
//break;
return imageArray[i].images;
}
}
}
//printResult(imageArray);
return [];
}
function printResult(resultArray){
for(var i=0;i<resultArray.length;i++) {
console.log(resultArray[i].name);
for(var j=0;j<resultArray[i].images.length;j++){
console.log(resultArray[i].images[j]);
}
}
}
images = compare(imageArray, totalValues);
if(images.length > 0){
for(var i=0;i<images.length; i++){
images[i].push({"url": "your url"});
}
}
Check out the javascript filter function (Link for the docs).
In your case, you want to do something like this:
function getImagesByAnimalName(animal_name){
var imageArray = imageslide.therapy;
var animalImages = imageArray.filter(animalData => {
return animalData.name === animal_name;
})
return animalImages[0].images;
}
Try it like this. The function will return URLs for each element in totalValues array.
var totalValues = ["cats"];
var slides = imageslide.therapy;
function comp(slides, totalValues ){
let retVal;
for( val of totalValues ) {
for( thisTh of slides ) {
if( thisTh.name == val ){
retVal = thisTh.images;
}
}
}
return retVal;
}
The following will create pics, a flat array of image URLs, if this is what you want:
var pics=[].concat(...imageslide.therapy.map(el=>{
if (totalValues.indexOf(el.name)>-1)
return el.images.map(e=>e.url)}))
console.log(pics);
function compare(imageArray, totalValues) {
for (var a = 0; a < imageArray.length; a++) {
for (var j = 0; j < totalValues.length; j++) {
if (totalValues[j] == imageArray[a].name) {
allValues.push(imageArray[a].images);
for (var i = 0; i < allValues.length; i++) {
for(var j = 0; j < allValues[i].length; j++){
buildSlide(allValues[i][j].url);
}
}
}
}
}
displaySlides(slide_index);
}

Small issue in javascript array object logic

I have an json array as below.If I find atleast one object with status as Active I need to set response =true or else false.I tried below but didnt worked .can someone help.
arr=[{"id":"1","status":"active"},{"id":"2","status":"complete"},
{"id":"3","status":"complete"}]
for (var i = 0; i < arr.len; i++) {
if (arr[i].status == "active") {
response = true;
} else {
response = false;
}
}
console.log(response);
Use Array#some to check if at least one element got status property with active value.
var arr = [{"id":"1","status":"active"},{"id":"2","status":"complete"},
{"id":"3","status":"complete"}],
response = arr.some(v => v.status == 'active');
console.log(response);
You set your response to true, don't break the loop and then set it to false again when you meet another value.
You may simply set initial condition and then break when you find an item. You can actually even not break when you find an item, but it is useless to continue iteration when already found an item.
var arr = [{
"id": "1",
"status": "active"
}, {
"id": "2",
"status": "complete"
},
{
"id": "3",
"status": "complete"
}
];
var response = false;
for (var i = 0; i < arr.length; i++) {
if (arr[i].status == "active") {
response = true;
break;
}
}
console.log(response);
Another elegant way is to use function and make a short-circuit return:
var arr = [{
"id": "1",
"status": "active"
}, {
"id": "2",
"status": "complete"
},
{
"id": "3",
"status": "complete"
}
];
function hasActiveStatus(a) {
for (var i = 0; i < a.length; i++) {
if (a[i].status == "active") {
return true;
}
}
return false;
}
var response = hasActiveStatus(arr);
console.log(response);
Note that you had .len for some reason, I have replaced it with correct .length.
Even more elegant way is to use Array.prototype.some:
var arr = [{
"id": "1",
"status": "active"
}, {
"id": "2",
"status": "complete"
},
{
"id": "3",
"status": "complete"
}
];
var response = arr.some(function(x) { return x.status === "active"; });
console.log(response);
var response = false;
var arr=[{"id":"1","status":"active"},{"id":"2","status":"complete"},
{"id":"3","status":"complete"}]
for (var i = 0; i < arr.length; i++) {
if (arr[i].status == "active") {
response = true;
break;
}
}
console.log(response);

JavaScript compare two arrays(key/value pairs) and copy value from one to the other if key matches

I have two arrays containing key/value pairs.
{
"containerOne": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": "ValueOne"
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": "ValueTwo"
}]
}
{
"containerTwo": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": null
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": "null
}
]
}
I'd like to compare both arrays and compare the title of each container. If the titles match, then I'd like to copy the Responsibility value from containerOne to containerTwo. The ID's will not match, so that can be ruled out. Only the titles will be consistent.
What is the most efficient way to do this please?]
Thanks
=====================================================================
EDIT
=====================================================================
Looking at the arrays a little closer, there is a subtle difference in the data being returned:
{
"AMLookupTasksList":
[
{
"Id":1,
"Title":"Create and Maintain an Onboarding Document",
"Responsibility":"1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
},
{
"Id":2,
"Title":"Execute Onboarding for New Consultants",
"Responsibility":"1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
}
]
}
{
"AMTasksList":
[
{
"Id":4,
"Title":
{
"$M_1":13,"$c_1":"Create and Maintain an Onboarding Document"
},
"Responsibility":null
},
{
"Id":17,
"Title":
{
"$M_1":12,"$c_1":"Execute Onboarding for New Consultants"
},
"Responsibility":null
}
]
}
Do I have additional looping to get to the Title value in the second array?
This might be a bit of overkill but it ignores the sequence and does a look up in each object.
I had to fix some syntax in your objects but I include that: named the objects and took a quote off one of the null values.
var obj1 = {
"containerOne": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": "ValueOne"
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": "ValueTwo"
}]
};
var obj2 = {
"containerTwo": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": null
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": null
}]
};
Now the code:
// lookup for first object:
var lookup = {};
// create referece to list above and use it everywhere
lookup.list = obj1;
for (var i = 0, len = lookup.list.containerOne.length; i < len; i++) {
lookup[lookup.list.containerOne[i].Title] = lookup.list.containerOne[i];
}
// lookup for second object
var otherLookup = {};
otherLookup.list = obj2;
for (var i = 0, len = otherLookup.list.containerTwo.length; i < len; i++) {
otherLookup[otherLookup.list.containerTwo[i].Title] = otherLookup.list.containerTwo[i];
}
// copy value for Responsibility from first to second on each matched in second.
var i = 0;
var len = lookup.list.containerOne.length;
for (i; i < len; i++) {
// looks up value from second list in the first one and if found, copies
if (lookup[otherLookup.list.containerTwo[i].Title]) {
otherLookup.list.containerTwo[i].Responsibility = lookup[otherLookup.list.containerTwo[i].Title].Responsibility;
}
}
// alerts new value using lookup
alert(otherLookup["TitleOne"].Responsibility);
EDIT for new structure, but same answer really:
var obj1 = {
"AMLookupTasksList": [{
"Id": 1,
"Title": "Create and Maintain an Onboarding Document",
"Responsibility": "1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
}, {
"Id": 2,
"Title": "Execute Onboarding for New Consultants",
"Responsibility": "1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
}]
};
var obj2 = {
"AMTasksList": [{
"Id": 4,
"Title": {
"$M_1": 13,
"$c_1": "Create and Maintain an Onboarding Document"
},
"Responsibility": null
}, {
"Id": 17,
"Title": {
"$M_1": 12,
"$c_1": "Execute Onboarding for New Consultants"
},
"Responsibility": null
}]
};
var lookup = {};
// create refernece to list above and use it everywhere
lookup.list = obj1;
for (var i = 0, len = lookup.list.AMLookupTasksList.length; i < len; i++) {
lookup[lookup.list.AMLookupTasksList[i].Title] = lookup.list.AMLookupTasksList[i];
}
var otherLookup = {};
otherLookup.list = obj2;
for (var i = 0, len = otherLookup.list.AMTasksList.length; i < len; i++) {
otherLookup[otherLookup.list.AMTasksList[i].Title.$c_1] = otherLookup.list.AMTasksList[i];
}
// copy value for Responsibility from first to second
var i = 0;
var len = otherLookup.list.AMTasksList.length;
for (i; i < len; i++) {
if (lookup[otherLookup.list.AMTasksList[i].Title.$c_1]) {
otherLookup.list.AMTasksList[i].Responsibility = lookup[otherLookup.list.AMTasksList[i].Title.$c_1].Responsibility;
}
}
alert(otherLookup["Create and Maintain an Onboarding Document"].Responsibility);
Fiddle for second answer: http://jsfiddle.net/n22V8/
First, create a dictionary from containerTwo:
var c2dict = {};
var c2i = containerTwo.innerContainer;
for (var i = 0; i < c2i.length; i++) {
c2dict[c2i[i].Title] = c2i[i];
}
Now use this to do the copying of propertyies when titles match:
var c1i = containerOne.innerContainer;
for (var i = 0; i < c1i.length; i++) {
if (c2dict[c1i[i].Title]) {
c2dict[c1i[i].Title].Property = c1i[i].Property;
}
}
You should compare properties and set them as the following:
containerOne.innerContainer.forEach(function (element,index) {
containerTwo.innerContainer.forEach(function (element2,index2) {
if (element.Title === element2.Title && element.Property != element2.Property) {
element2.Property = element.Property;
}
});
});

Categories