Any ideas on JQuery mapping that will return an array of duplicates names, and titles, with their count. So I can create a bar graph in D3 or Chart JS (Chart JS seems easier so far)...
ie, I have (example, using JSON)
obj = {"Chocolate":"Organic", "Chocolate":"Fresh", "Chocolate":"Organic",
"Vanilla":"Regular",
"Vanilla":"Organic","Strawberry":"Fresh","Vanilla":"Regular"};
I want this
var data = {
labels: ["Chocolate", "Strawberry", "Vanilla"],
datasets: [
{
label: "Fresh",
fillColor: "blue",
data: [1,0,1] //(1 Fresh chocolate, 1 Fresh Strawberry, No fresh Vanilla)
},
{
label: "Regular",
fillColor: "red",
data: [0,0,2] //(0 regular chocolate, 0 regular Strawberry, 2 regular Vanilla)
},
{
label: "Organic",
fillColor: "green",
data: [2,1,0] //(2 organic chocolate, 1 organic Vanilla, 0 organic strawberry)
}
]
};
http://jsfiddle.net/u25c7gtj/2/
What have I tried? Well so far I have been able to group the items by Chocolate, Vanilla, or Strawberry, but the next step of getting a count of the items that have matching properties... I don't even know where to begin comparing them. I tried only pulling the "Flavor and Type", to compare those as objects but the comparison only yielded the groups with the individual flavor and type key and value pairs.
function groupBy(propertyName, array) {
var groupedElements = {};
for(var i = 0; i < array.length; i++) {
var element = array[i];
var value = element[propertyName];
var group = groupedElements[value];
if(group == undefined) {
group = [element];
groupedElements[value] = group;
} else {
group.push(element);
}
}
return groupedElements;
}
var result = groupBy("flavor", obj)
console.log(result);
$("#results").html(JSON.stringify(result, null, 4));
I also tried the code below which only seems to count the total
<script type="text/javascript">
$.ajax({
url: "/_api/web/lists/getbytitle('Ice Cream List')/items?$select=ID,Flavor,Type",
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
},
success: function(data){
// $.each(data.d.results, function(index, item){
// console.log(item.Id);
// console.log(item.Title);
// console.log(item.m4gs);
// });
var counts = [];
jQuery.each(data.d.results, function(index, item) {
if (!counts.hasOwnProperty(item)) {
counts[item] = 1;
} else {
counts[item]++;
}
});
console.log(counts[]);
Related
I am trying to add the values of multiple arrays (one starts out empty, but all the ones I am adding to it are the same length, though it be great if we could come up with something that adds them even if they are all different lengths) - not the sum of all values in each array, instead, sum of the values in the same index. For example:
array1 = [1, 2, 3]
array2 = [2, 3, 4]
desiredArray = [3, 5, 7]
The number of the arrays I will be adding is arbitrary, as they are created based on the users selection. (Based on the length of the array created from the selection). I want to sum the arrays by index to create a new array, and from the new array, I will create a decline curve. When I attempt to add them using "indexSum" I get an array below back full of NaaNs...though they are the correct legth:
requestedOil
requestedGas
requestedWater
These are the temporary arrays created by the length of the var "values" - these are the ones I am trying to add by respective index to eventually get the ones mentioned above:
Oil[well]
Gas[well]
Water[well]
THIS IS THE FUNCTON I CURRENTLY HAVE TO ADD ARRAYS AND CALLED WHEN USER MAKES SELECTION FROM multiple-site-selection
function updateCurves(){
var dropdownMenu = document.getElementById("multiple-site-selection").selectedOptions;
var values = Array.from(dropdownMenu).map(({ value }) => value);
console.log(values);
d3.json('./static/wellNames.json').then((data) => { //read in the wellNames.json file, which contains the array "names" with all the well names
wellOptions = data.names;
forSelection = wellOptions.map((x) => ({id:x}))
console.log(forSelection);
d3.json("./static/all_production.json").then((data) =>{
var requestedOil = [];
var requestedGas = [];
var requestedWater = [];
var site_date = [];
var Oil = [];
var Gas = [];
var Water = [];
values.forEach((well) => {
forSelection.forEach((pair) => {
if(well == Object.values(pair)){
Oil[well] = new Array();
Gas[well] = new Array();
Water[well] = new Array();
new Promise ((resolve) => data.forEach((site) => {
if(values.length == 1 && well == site[0]){
requestedOil.push(site[2]);
requestedGas.push(site[3]);
requestedWater.push(site[4]);
site_date.push(site[8])}
else if(values.length > 1 && well == site[0]){
indexSum = (a1, a2) => a1.map((v, i) => i + a2[v]);
Oil[well].push(site[2])
requestedOil = indexSum(Oil[well], requestedOil);
Gas[well].push(site[3])
requestedGas = indexSum(Gas[well], requestedGas);
Water[well].push(site[4])
requestedWater = indexSum(Water[well], requestedWater);
site_date.push(site[8])}
else{}
resolve()}))//PROMISE CLOSED
} //IF CLOSED
})//forSelection (dic containing names of well selected) closed
console.log(Oil[well]);
}); //values.forEach closed
THIS CODE CURRENTLY WORKS AS I AM NOT ADDING ANY ARRAYS AND IT IS CALLED AS SOON AS THE WEBPAGE LOADS
//FUNCTION TO CREATE DROP DOWN VALUES
function createDropdownOptions() {
var selector = d3.select("#multiple-site-selection"); //select dropdown <select> in well.html with id:"siteSelection"
d3.json('./static/wellNames.json').then((data) => { //read in the wellNames.json file, which contains the array "names" with all the well names
var wellOptions = data.names;
wellOptions.forEach((well) => {
selector
.append('option')
.text(well)
.property('Value', well);
})
})
};
createDropdownOptions(); //CALL FUNCTION TO CREATE DROPDOWN MENU VALUES
// //FUNCTION TO CREATE HOME/SUMMARY CURVES
function curvesHome() {
d3.json("./static/all_production.json").then((data) =>{ //THIS WORKS!!!
var site_oil = [];
var site_gas = [];
var site_water = [];
summarySiteDate = [];
new Promise ((resolve) => data.forEach(site => {if (site[0]==="Summary") {
site_oil.push(site[2]);
site_gas.push(site[3]);
site_water.push(site[4]);
summarySiteDate.push(site[8]);
} resolve()}));
//CALL FUNCTION TO CREATE DROPDOWN MENU VALUES
var mostRecentEntry = summarySiteDate[0]; //MOST RECENT DATE WITHOUT HOUR AS VARIABLE
var addingHours = "T00:00"; //HOURS TO ADD TO MOST RECENT DATE - NEEDED TO NORMALIZE FROM ORIGINAL 19 HOUR FORMAT
var nextYear = mostRecentEntry.concat(addingHours); //DATE AND HOUR AS SINGLE VARIABLE TO MAKE INTO DATE
var mostRecentDate = new Date(nextYear); //MAKE VARIABLE INTO DATE
var nextYearsDate = new Date(mostRecentDate.setFullYear(mostRecentDate.getFullYear() + 1)); //GET YEAR FROM MOST RECENT DATE AND ADD A YEAR
var nextYear= nextYearsDate.getFullYear() //GET NEXT YEARS DATE
var nextMonth= nextYearsDate.getMonth() + 1 // GET NEXTS YEARS MONTH, ADD ONE BECAUSE MONTHS ARE INDEXED AT 0
var nextDate= nextYearsDate.getDate() //GET NEXT YEARS DATE
nextYearGraph = `${nextYear}-${nextMonth}-${nextDate}`; // CREATE FULL DATE FOR NEXT YEAR IN RIGHT FORMAT FOR AXIS
console.log(`${nextYearGraph} is a year from the most recent production date. This is from curvesHome()`);
var dataOil = [{
x: summarySiteDate,
y: site_oil,
type: "line",
line:
{color: "green"}
}];
var layoutOil = {
title: "Oil BBL",
yaxis: {
type: 'log',
autorange: true
},
xaxis: {
autorange: false,
range: [summarySiteDate[summarySiteDate.length-1], nextYearGraph]
}
};
Plotly.newPlot("oilDeclineCurve", dataOil, layoutOil);
// gas decline curve data
var dataGas = [{
x: summarySiteDate,
y: site_gas,
type: "line",
line: {color: "red"}
}];
var layoutGas = {
title: "Gas BBL",
yaxis: {
type: 'log',
autorange: true
},
xaxis: {
autorange: false,
range: [summarySiteDate[summarySiteDate.length-1], nextYearGraph]
}
};
Plotly.newPlot("gasDeclineCurve", dataGas, layoutGas);
// water decline curve data
var dataWater = [{
x: summarySiteDate,
y: site_water,
type: "line" }
];
var layoutWater = {
title: "Water BBL",
yaxis: {
type: 'log',
autorange: true
},
xaxis: {
autorange: false,
range: [summarySiteDate[summarySiteDate.length-1], nextYearGraph]
}
};
Plotly.newPlot("waterDeclineCurve", dataWater, layoutWater);
})};
I have both HTML sand JS in my code, so it is probably best if you have the whole thing to better understand what I am doing and trying to do. Here are my links:
My repo:
My GitPage
Thank you in advanced!
Here is a function that bases length off of first array length and doesn't care about the number of input arrays
function stackSum(arr) {
return arr[0].map((a, i) => {
let r = 0;
arr.forEach(b, j) => r+=arr[j][i]);
return r;
})
}
console.log(stackSum([
[1,1,1],
[1,2,2],
[2,2,3],
[3,7,7]
]).join(','));
console.log(stackSum([
[1,2,3],
[2,3,4]
]).join(','));
Since the arrays are of equal lengths, you can simply use Array#map.
const
indexSum = (a1, a2) => a1.map((v, i) => v + a2[i]),
desiredArray = indexSum([1, 2, 3], [4, 5, 6])
console.log(desiredArray)
I am requesting a webservice, which responds with a CSV file like this (with more monthly data available for the last years). Important for me are the first and last piece of information in the line (aka date and value):
2010/01/01,51.67074582499006,13.789093928493081,-0.0010074468085106377
2010/02/01,51.67074582499006,13.789093928493081,0.0024117021276595747
2010/03/01,51.67074582499006,13.789093928493081,0.026550000000000004
2010/04/01,51.67074582499006,13.789093928493081,0.08252659574468087
2010/05/01,51.67074582499006,13.789093928493081,0.12837446808510639
2010/06/01,51.67074582499006,13.789093928493081,0.140618085106383
2010/07/01,51.67074582499006,13.789093928493081,0.0668787234042553
2010/08/01,51.67074582499006,13.789093928493081,0.10335744680851064
2010/09/01,51.67074582499006,13.789093928493081,0.08095000000000001
2010/10/01,51.67074582499006,13.789093928493081,0.0400159574468085
2010/11/01,51.67074582499006,13.789093928493081,0.004214893617021277
2010/12/01,51.67074582499006,13.789093928493081,-0.0018680851063829788
2011/01/01,51.67074582499006,13.789093928493081,0.0011914893617021279
2011/02/01,51.67074582499006,13.789093928493081,0.003752127659574468
2011/03/01,51.67074582499006,13.789093928493081,0.027225531914893623
With this information, I would like to build a Highcharts graphic, which displays a separate line for each individual year. It should look like this:
My current version adds all data up to a long line - which is nice, but doesn't make the values comparable between the years:
function processData(allText)
{
var allTextLines = allText.split(/\r\n|\n/);
var lines = []; var n = 0; var data = []; var dateValue = [];
for (var i=1; i<allText.length; i++)
{
if (allTextLines[i])
{
if ((allTextLines[i].substring(0,2) == "19") || (allTextLines[i].substring(0,2) == "20"))
{
dateValue = allTextLines[i].split(",");
// everything will be concatenated into one single line
if(Number.isFinite(parseFloat(dateValue[3])))
{
data[n] = [new Date(dateValue[0]).getTime(), parseFloat(dateValue[3])];
}
n++;
}
}
}
return data;
}
Now, what I need is a result which looks like this:
series:
[{
name: "2010",
data: [-0.001007447,0.002411702,0.02655,0.082526596,0.128374468,0.140618085,0.066878723,0.103357447,0.08095,0.040015957,0.004214894,-0.001868085]
},{
name: "2011",
data: [0.001191489,0.003752128,0.027225532,0.090589362,0.129121277,0.141264894,0.119343617,0.113290426,0.093575532,0.044221277,0.015881915,0.004068085]
}
],
...
But I have no idea how my Javascript code must look like, to generate such an outcome. Can anyone give me a hint?
You can extract your data like this :
function extract(csv) {
var rows = csv.split(/\r\n|\n/);
var data;
var series = [];
var serie = {name: -1, data: []};
for (var i = 0; i < rows.length; i++) {
data = rows[i].split(',');
if (serie.name === -1) {
serie.name = data[0].substr(0,4);
}
else if (serie.name !== data[0].substr(0,4)) {
series.push(serie);
serie = {name: data[0].substr(0,4), data: []};
}
serie.data.push(parseFloat(data[3]));
}
series.push(serie);
return series;
}
jsFiddle : https://jsfiddle.net/mk7x7bbe/
$.each(constructions, function(i,v) {
if ($.inArray(v.name, map[ii].buildings) == -1) {//stuff}
};
Where constructions is an array of objects, each with a unique name. map[ii].buildings is an array containing some of these objects. I want to iterate each object in constructions, checking if its name parameter appears in the objects of map[ii].buildings.
The above code works if the each element in the map[ii].buildings array is just the text string of the object name, but not if the element is the entire object.. close, but no dice >.<
Try using $.grep() instead of $.inArray(); you can specify a function to do the filtering for you.
Instead of checking for -1, you check whether the array that $.grep() returns has length == 0
Simple example: (would be easier if you posted the code / example of what "constructions" objects look like)
var constructions = [{
Name: "Mess hall",
SqFt: 5000
}, {
Name: "Infirmary",
SqFt: 2000
}, {
Name: "Bungalow",
SqFt: 2000
}, {
Name: "HQ",
SqFt: 2000
}];
var buildings = [{
Name: "Infirmary",
SqFt: 2000
}, {
Name: "HQ",
SqFt: 2000
}];
// found buildings will be list of items in "constructions" that is not in "buildings"
var foundBuildings = $.grep(constructions, function (constructionsItem) {
return $.grep(buildings, function (buildingsItem) {
return buildingsItem.Name === constructionsItem.Name
}).length == 0; // == 0 means "not in", and > 0 means "in"
});
// this just renders the results all pretty for ya
$.each(foundBuildings, function (idx, item) {
$("#output").append("<div>" + item.Name + "</div>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='output'></div>
Example jsFiddle: http://jsfiddle.net/eLeuy9eg/3/
The non-jQuery way of doing this would be to use filter. Something like this:
// pass in an array and the key for which you want values
// it returns an array of those values
function getValues(arr, key) {
return arr.map(function (el) { return el[key]; });
}
function notFoundIn(arr, arr2) {
// grab the names of the buildings
var buildings = getValues(arr2, 'name');
// grab the names from the construction objects and filter
// those that are not in the building array
return getValues(arr, 'name').filter(function (el) {
return buildings.indexOf(el) === -1;
});
}
notFoundIn(constructions, buildings); // eg [ "one", "three" ]
DEMO
You could even add a new method to the array prototype. With this one you can use either simple arrays, or arrays of objects if you pass in a key. Note in this example I've replaced map and filter with loops that perform the same functions, but faster (see comments):
function getValues(arr, key) {
var out = [];
for (var i = 0, l = arr.length; i < l; i++) {
out.push(arr[i][key]);
}
return out;
}
if (!Array.prototype.notFoundIn) {
Array.prototype.notFoundIn = function (inThisArray, key) {
var thisArr = key ? getValues(this, key) : this;
var arrIn = key ? getValues(inThisArray, key) : inThisArray;
var out = [];
for (var i = 0, l = thisArr.length; i < l; i++) {
if (arrIn.indexOf(thisArr[i]) === -1) {
out.push(thisArr[i]);
}
}
return out;
}
}
constructions.notFoundIn(buildings, 'name');
[1, 2, 3].notFoundIn([2]); // [1, 3]
DEMO
I am trying to figure out an efficient way to remove objects that are duplicates from an array and looking for the most efficient answer. I looked around the internet everything seems to be using primitive data... or not scalable for large arrays. This is my current implementation which is can be improved and want to try to avoid labels.
Test.prototype.unique = function (arr, artist, title, cb) {
console.log(arr.length);
var n, y, x, i, r;
r = [];
o: for (i = 0, n = arr.length; i < n; i++) {
for (x = 0, y = r.length; x < y; x++) {
if (r[x].artist == arr[i].artist && r[x].title == arr[i].title) {
continue o;
}
}
r.push(arr[i]);
}
cb(r);
};
and the array looks something like this:
[{title: sky, artist: jon}, {title: rain, artist: Paul}, ....]
Order does not matter, but if sorting makes it more efficient then I am up for the challenge...
and for people who do not know o is a label and it is just saying jump back to the loop instead of pushing to the new array.
Pure javascript please no libs.
ANSWERS SO FAR:
The Performance Test for the answers below:
http://jsperf.com/remove-duplicates-for-loops
I see, the problem there is that the complexity is squared. There is one trick to do it, it's simply by using "Associative arrays".
You can get the array, loop over it, and add the value of the array as a key to the associative array. Since it doesn't allow duplicated keys, you will automatically get rid of the duplicates.
Since you are looking for title and artist when comparing, you can actually try to use something like:
var arrResult = {};
for (i = 0, n = arr.length; i < n; i++) {
var item = arr[i];
arrResult[ item.title + " - " + item.artist ] = item;
}
Then you just loop the arrResult again, and recreate the array.
var i = 0;
var nonDuplicatedArray = [];
for(var item in arrResult) {
nonDuplicatedArray[i++] = arrResult[item];
}
Updated to include Paul's comment. Thanks!
Here is a solution that works for me.
Helper functions:
// sorts an array of objects according to one field
// call like this: sortObjArray(myArray, "name" );
// it will modify the input array
sortObjArray = function(arr, field) {
arr.sort(
function compare(a,b) {
if (a[field] < b[field])
return -1;
if (a[field] > b[field])
return 1;
return 0;
}
);
}
// call like this: uniqueDishes = removeDuplicatesFromObjArray(dishes, "dishName");
// it will NOT modify the input array
// input array MUST be sorted by the same field (asc or desc doesn't matter)
removeDuplicatesFromObjArray = function(arr, field) {
var u = [];
arr.reduce(function (a, b) {
if (a[field] !== b[field]) u.push(b);
return b;
}, []);
return u;
}
and then simply call:
sortObjArray(dishes, "name");
dishes = removeDuplicatesFromObjArray(dishes, "name");
Basic sort-then-unique implementation, fiddle HERE:
function unique(arr) {
var comparer = function compareObject(a, b) {
if (a.title == b.title) {
if (a.artist < b.artist) {
return -1;
} else if (a.artist > b.artist) {
return 1;
} else {
return 0;
}
} else {
if (a.title < b.title) {
return -1;
} else {
return 1;
}
}
}
arr.sort(comparer);
console.log("Sorted: " + JSON.stringify(arr));
for (var i = 0; i < arr.length - 1; ++i) {
if (comparer(arr[i], arr[i+1]) === 0) {
arr.splice(i, 1);
console.log("Splicing: " + JSON.stringify(arr));
}
}
return arr;
}
It may or may not be the most efficient, and should be entirely scalable. I've added some console.logs so you can see it as it works.
EDIT
In the interest of saving on the space the function used, I did that for loop at the end, but it seems likely that didn't properly find only unique results (depsite it passing my simple jsfiddle test). Please try replacing my for loop with the following:
var checker;
var uniqueResults = [];
for (var i = 0; i < arr.length; ++i) {
if (!checker || comparer(checker, arr[i]) != 0) {
checker = arr[i];
uniqueResults.push(checker);
}
}
return uniqueResults;
I use this function. its not doing any sorting, but produces result. Cant say about performance as never measure it.
var unique = function(a){
var seen = [], result = [];
for(var len = a.length, i = len-1; i >= 0; i--){
if(!seen[a[i]]){
seen[a[i]] = true;
result.push(a[i]);
}
}
return result;
}
var ar = [1,2,3,1,1,1,1,1,"", "","","", "a", "b"];
console.log(unique(ar));// this will produce [1,2,3,"", "a", "b"] all unique elements.
Below is Henrique Feijo's answer with ample explanation and an example that you can cut and paste:
Goal: Convert an array of objects that contains duplicate objects (like this one)...
[
{
"id": 10620,
"name": "Things to Print"
},
{
"id": 10620,
"name": "Things to Print"
},
{
"id": 4334,
"name": "Interesting"
}
]
... Into an array of objects without duplicate objects (like this one):
[
{
"id": 10620,
"name": "Things to Print"
},
{
"id": 4334,
"name": "Interesting"
}
]
Explanation provided in the comments:
var allContent = [{
"id": 10620,
"name": "Things to Print"
}, {
"id": 10620,
"name": "Things to Print"
}, {
"id": 4334,
"name": "Interesting"
}]
//Put Objects Into As Associative Array. Each key consists of a composite value generated by each set of values from the objects in allContent.
var noDupeObj = {} //Create an associative array. It will not accept duplicate keys.
for (i = 0, n = allContent.length; i < n; i++) {
var item = allContent[i]; //Store each object as a variable. This helps with clarity in the next line.
noDupeObj[item.id + "|" + item.name] = item; //This is the critical step.
//Here, you create an object within the associative array that has a key composed of the two values from the original object.
// Use a delimiter to not have foo+bar handled like fo+obar
//Since the associative array will not allow duplicate keys, and the keys are determined by the content, then all duplicate content are removed.
//The value assigned to each key is the original object which is along for the ride and used to reconstruct the list in the next step.
}
//Recontructs the list with only the unique objects left in the doDupeObj associative array
var i = 0;
var nonDuplicatedArray = [];
for (var item in noDupeObj) {
nonDuplicatedArray[i++] = noDupeObj[item]; //Populate the array with the values from the noDupeObj.
}
console.log(nonDuplicatedArray)
For those who love ES6 and short stuff, here it's one solution:
const arr = [
{ title: "sky", artist: "Jon" },
{ title: "rain", artist: "Paul" },
{ title: "sky", artist: "Jon" }
];
Array.from(arr.reduce((a, o) => a.set(o.title, o), new Map()).values());
const arr = [
{ title: "sky", artist: "Jon" },
{ title: "rain", artist: "Paul" },
{ title: "sky", artist: "Jon" },
{ title: "rain", artist: "Jon" },
{ title: "cry", artist: "Jon" }
];
const unique = Array.from(arr.reduce((a, o) => a.set(o.title, o), new Map()).values());
console.log(`New array length: ${unique.length}`)
console.log(unique)
The above example only works for a unique title or id. Basically, it creates a new map for songs with duplicate titles.
Below code compares object with JSON as String format and removes duplicates and works fine with simple arrays.
Array.prototype.unique=function(a){
return function(){
return this.filter(a)
}
}(
function(a,b,c){
var tmp=[];
c.forEach(function(el){
tmp.push(JSON.stringify(el))
});
return tmp.indexOf(JSON.stringify(a),b+1)<0
})
If you are using underscore js, it is easy to remove duplicate object.
http://underscorejs.org/#uniq
function remove_duplicates(objectsArray) {
var arr = [], collection = [];
$.each(objectsArray, function (index, value) {
if ($.inArray(value.id, arr) == -1) {
arr.push(value.id);
collection.push(value);
}
});
return collection;
}
I have two arrays (data and data_not_included).Each elemet of those arrays has attridutes id and name. I fill them this way:
data[i] = {
name :products.models[i].get('name'),
id : products.models[i].get('id')
};
Now I want do display the elements in data which are not in data_not_included array. For example I have
data=[{name: Sugar}{id: 1},{name: Butter}{id: 2},{name: Cola}{id: 3}]
// and
data_nat_included = [{name: Sugar}{id: 1},{name: Butter}{id: 2}].
It should display {name: Cola}{id: 3} only.
Here is what I have already done:
for(var j=0;j<data_not_icluded.length;j++)
{
for(var i=0;i<data.length;i++)
{
if(data[i].id != data_not_icluded[j].id ){
//but this doesnt work for me it displayes a lot of element many times
}
}
}
Both answers are asymptotically bad. This means they run in suboptimal time. In other words, they are naive approaches to solving the problem. This problem is more widely known in the domain of databases, where join operation is a commonplace. It is also known that the complexity of a join is O(log n * n + log m * m) where n is the number of elements in first table and m is the number of elements in the second table. This is fewer operations then would be required by naive solution offered in other examples O(n^2).
However, if more is known about your data, as, for example, I would expect that the values are unique and easily serializable to string, you could even reduce the complexity to O(n + m) by simply creating hashes of the objects you want to compare. Here's how to do it:
Where n is the number of elements in the first array and m is the number of elements in the second array.
var data = [{ name: "Sugar" },
{ id: 1 },
{ name: "Butter" },
{ id: 2 },
{ name: "Cola" },
{ id: 3 }];
var dataNatIncluded = [{ name: "Sugar" },
{ id: 1 },
{ name: "Butter" },
{ id: 2 }];
function join(a, b) {
var hashA = {}, hashB = {}, p, result = [];
function setter(hash) {
return function (element) { hash[JSON.stringify(element)] = element; };
}
a.forEach(setter(hashA));
b.forEach(setter(hashB));
for (p in hashB) delete hashA[p];
for (p in hashA) result.push(hashA[p]);
return result;
}
// [{ name: "Cola" }, { id: 3 }]
A simple way to do that:
var vals = [];
for(var i=0;i<data.length;i++)
{
var found = false;
for(var j=0;j<data_nat.length;j++)
{
if(data[i].id == data_nat[j].id ){
found = true;
break;
}
}
if (!found) vals.push(data[i]);
}
JSFiddle
for(var j=0;j<data_not_icluded.length;j++)
for(var i=0;i<data.length;i++)
if(data[i].id != data_not_icluded[j].id )
Think of what this does: For any not included object, show all objects that have not the same id as the current not included one. This will show many items multiple times, and it will show objects that are in "not included" but at another position.
Instead, loop over data, check each that it is not included in data_not_included, and display it otherwise:
dataloop: for (var i=0; i<data.length; i++) {
for (var j=0; j<data_not_included.length; j++)
if (data[i].id == data_not_icluded[j].id)
continue dataloop;
display(data[i]);
}
Or, using some iteration methods of Arrays:
data.filter(function(d) {
return data_not_included.every(function(n) {
return d.id != n.id;
});
}).each(display);