Find duplicate values between two separate javascript objects? - javascript

I have two javascript arrays of objects:
var fullDateRange=[{date:"4/1/18",value:0},{date:"4/2/18",value:0},{date:"4/3/18",value:0},{date:"4/4/18",value:0},{date:"4/5/18",value:0}]
and
var actualDateRange=[{date:"4/1/18",value:1},{date:"4/3/18",value:3},{date:"4/5/18",value:5}]
I'm trying to loop through the fullDateRange array, see if any of the actualDateRange dates exist, and increment the value. But I keep getting duplicates with this code:
function outputDeltaDates(fullDateObj, responseObj) {
var dateArr = [],
valueArr = [];
$.each(fullDateObj, function(index) {
var fullDate = this;
var counter = 0
$.each(responseObj, function(index) {
var fullResponse = this;
if (fullResponse['date'] == fullDate['date']) {
valueArr.push(fullResponse['value'])
dateArr.push(fullDate['date'])
} else {
if (!dateArr.includes(fullDate['date'])) {
valueArr.push(0)
dateArr.push(fullDate['date'])
}
}
})
})
return [valueArr, dateArr]
}

To increment the objects value property if the date exists in the other array, simply loop it once and increment value if the date is found in actualDateRange
var fullDateRange=[{date:"4/1/18",value:0},{date:"4/2/18",value:0},{date:"4/3/18",value:0},{date:"4/4/18",value:0},{date:"4/5/18",value:0}]
var actualDateRange=[{date:"4/1/18",value:1},{date:"4/3/18",value:3},{date:"4/5/18",value:5}]
fullDateRange.forEach(e => {
let act = actualDateRange.find(a => a.date === e.date);
if (act) e.value += act.value;
})
console.log(fullDateRange);

To achieve expected result, push incremented counter to valueArr i.e
valueArr.push(++counter)
instead of
fullResponse['value'] (which will push actualDateRange value)
var fullDateRange=[{date:"4/1/18",value:0},{date:"4/2/18",value:0},{date:"4/3/18",value:0},{date:"4/4/18",value:0},{date:"4/5/18",value:0}]
var actualDateRange=[{date:"4/1/18",value:1},{date:"4/3/18",value:3},{date:"4/5/18",value:5}]
function outputDeltaDates(fullDateObj, responseObj) {
var dateArr = [],
valueArr = [];
$.each(fullDateObj, function(index) {
var fullDate = this;
var counter = 0
$.each(responseObj, function(index) {
var fullResponse = this;
if (fullResponse['date'] == fullDate['date']) {
valueArr.push(++counter)
dateArr.push(fullDate['date'])
} else {
if (!dateArr.includes(fullDate['date'])) {
valueArr.push(0)
dateArr.push(fullDate['date'])
}
}
})
})
return [valueArr, dateArr]
}
console.log(outputDeltaDates(fullDateRange, actualDateRange))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
code sample - https://codepen.io/nagasai/pen/rvVqdW?editors=1010

Related

JavaScript array has elements but length is zero

I've done some searching around the web and nothing seems to solve my problem. I have the following jQuery code:
function youtube_data_parser(data) {
//---> parse video data - start
var qsToJson = function(qs) {
var res = {};
var pars = qs.split('&');
var kv, k, v;
for (i in pars) {
kv = pars[i].split('=');
k = kv[0];
v = kv[1];
res[k] = decodeURIComponent(v);
}
return res;
}
//---> parse video data - end
var get_video_info = qsToJson(data);
if (get_video_info.status == 'fail') {
return {
status: "error",
code: "invalid_url",
msg: "check your url or video id"
};
} else {
// remapping urls into an array of objects
//--->parse > url_encoded_fmt_stream_map > start
//will get the video urls
var tmp = get_video_info["url_encoded_fmt_stream_map"];
if (tmp) {
tmp = tmp.split(',');
for (i in tmp) {
tmp[i] = qsToJson(tmp[i]);
}
get_video_info["url_encoded_fmt_stream_map"] = tmp;
}
//--->parse > url_encoded_fmt_stream_map > end
//--->parse > player_response > start
var tmp1 = get_video_info["player_response"];
if (tmp1) {
get_video_info["player_response"] = JSON.parse(tmp1);
}
//--->parse > player_response > end
//--->parse > keywords > start
var keywords = get_video_info["keywords"];
if (keywords) {
key_words = keywords.replace(/\+/g, ' ').split(',');
for (i in key_words) {
keywords[i] = qsToJson(key_words[i]);
}
get_video_info["keywords"] = {
all: keywords.replace(/\+/g, ' '),
arr: key_words
};
}
//--->parse > keywords > end
//return data
return {
status: 'success',
raw_data: qsToJson(data),
video_info: get_video_info
};
}
}
function getVideoInfo() {
var get_video_url = $('#ytdlUrl').val();
var get_video_id = getUrlVars(get_video_url)['v'];
var video_arr_final = [];
var ajax_url = "video_info.php?id=" + get_video_id;
$.get(ajax_url, function(d1) {
var data = youtube_data_parser(d1);
var video_data = data.video_info;
var player_info = data.video_info.player_response;
var video_title = player_info.videoDetails.title.replace(/\+/g, ' ');
var fmt_list = video_data.fmt_list.split(',');
var video_thumbnail_url = video_data.thumbnail_url;
var video_arr = video_data.url_encoded_fmt_stream_map;
//create video file array
$.each(video_arr, function(i1, v1) {
var valueToPush = {};
valueToPush.video_url = v1.url;
valueToPush.video_thumbnail_url = video_thumbnail_url;
valueToPush.video_title = video_title;
$.each(fmt_list, function(i2, v2) {
var fmt = v2.split('/');
var fmt_id = fmt[0];
var fmt_quality = fmt[1];
if (fmt_id == v1.itag) {
valueToPush.fmt_id = fmt_id;
valueToPush.fmt_quality = fmt_quality;
}
});
video_arr_final.push(valueToPush);
});
});
return video_arr_final;
}
function getUrlVars(url) {
var vars = {};
var parts = url.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m, key, value) {
vars[key] = value;
});
return vars;
}
function fillInOptions(ytOptions) {
//console.log(ytOptions);
//alert(ytOptions[0]);
var ytFill = ytOptions;
console.log(ytFill);
//ytFill.forEach(function(i,v) {
var ytdlOptions = $('#ytdlOptions');
ytFill.forEach(function(i,v) {
console.log(i);
ytdlOptions.append(new Option(v.fmt_quality, v.fmt_id));
});
return true;
}
function showYTDLLoader() {
$('#ytdlInput').fadeOut(1000, function() {
$('#ytdlLoader').fadeIn(500);
});
var options = getVideoInfo();
//console.log(options);
if (fillInOptions(options) == true) {
//do rest
}
}
function showYTDLOptions() {
return true;
}
function startDownload() {
showYTDLLoader();
}
function hideYTDLLoader() {
$('#ytdlLoader').fadeOut(500);
}
function animateCSS(element, animationName, callback) {
const node = $(element);
node.addClass(animationName);
function handleAnimationEnd() {
node.removeClass(animationName);
node.animationend = null;
if (typeof callback === 'function') callback();
}
node.animationend = handleAnimationEnd();
}
When my button is clicked, I call showYTDLLoader() which gets an array of objects from the YouTube API that looks like this:
[
{
"video_url": "https://r7---sn-uxanug5-cox6.googlevideo.com/videoplayback?expire=1572496003&ei=Iw66Xa24H8PL3LUPiN25mAs&ip=2001%3A8003%3A749b%3Aa01%3A5cd8%3Ac610%3A6402%3Ad0fe&id=o-ADsVnoOoBQ6-SWzYZU7gHES06s7xQptJG6hn9WcakITY&itag=22&source=youtube&requiressl=yes&mm=31%2C29&mn=sn-uxanug5-cox6%2Csn-ntqe6n7r&ms=au%2Crdu&mv=m&mvi=6&pl=39&initcwndbps=1655000&mime=video%2Fmp4&ratebypass=yes&dur=917.768&lmt=1572418007364260&mt=1572474311&fvip=4&fexp=23842630&c=WEB&txp=5535432&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cmime%2Cratebypass%2Cdur%2Clmt&sig=ALgxI2wwRgIhAIp-4gyUTLoXFetbY0ha_YnR7DJqsp_MNjjIxqDdfPZJAiEA_WPd21jgX9broBcigf8rcSEVoJb2_NX7t3XZQqytsSM%3D&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHylml4wRAIgacvP3zjEq-rVEZFrX7a_hC6TR-Zab7Ii-Fbaupjs_PcCIHdZht4l4ioYL3ERz7WNiSbnOnhm5iYxEECaQXPP2hUp",
"video_title": "Arnold Schwarzenegger on Son-in-law Chris Pratt, Pranking Sylvester Stallone & Terminator’s Return",
"fmt_id": "22",
"fmt_quality": "1280x720"
},
{
"video_url": "https://r7---sn-uxanug5-cox6.googlevideo.com/videoplayback?expire=1572496003&ei=Iw66Xa24H8PL3LUPiN25mAs&ip=2001%3A8003%3A749b%3Aa01%3A5cd8%3Ac610%3A6402%3Ad0fe&id=o-ADsVnoOoBQ6-SWzYZU7gHES06s7xQptJG6hn9WcakITY&itag=18&source=youtube&requiressl=yes&mm=31%2C29&mn=sn-uxanug5-cox6%2Csn-ntqe6n7r&ms=au%2Crdu&mv=m&mvi=6&pl=39&initcwndbps=1655000&mime=video%2Fmp4&gir=yes&clen=44248820&ratebypass=yes&dur=917.768&lmt=1572416976690256&mt=1572474311&fvip=4&fexp=23842630&c=WEB&txp=5531432&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cmime%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&sig=ALgxI2wwRQIhANTZJlBHFWQWCnfK11yvLiPUV26c6NzvqIMKjDwmsByMAiBUSy0ZJMo4GdHSiRU4xBDDLxLtzwKZAqAKCiB-1aViDQ%3D%3D&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHylml4wRAIgacvP3zjEq-rVEZFrX7a_hC6TR-Zab7Ii-Fbaupjs_PcCIHdZht4l4ioYL3ERz7WNiSbnOnhm5iYxEECaQXPP2hUp",
"video_title": "Arnold Schwarzenegger on Son-in-law Chris Pratt, Pranking Sylvester Stallone & Terminator’s Return",
"fmt_id": "18",
"fmt_quality": "640x360"
}
]
But when I try and loop through each entry with fillInOptions(), my loop is never completed because the length is apparently zero. However, when I dump the array using console.log() it tells me the length is 2, and displays the above. I need to be able to add each option to my dropdown.
Thankyou!
UPDATE: Added full code, sorry!
It looks like your .forEach() is the root of the problem. The parameters of a forEach are currentValue, index like this: array.forEach(function(currentValue, index) {}); but it looks like you're using them in the opposite way
Try rewriting that iteration to this:
ytFill.forEach(function(v, i) {
console.log(i);
ytdlOptions.append(new Option(v.fmt_quality, v.fmt_id));
});
Notice the difference in the order of v and i in the parameters.

Delete duplicate object(JSON) nodes - JavaScript

I have a JSON string:
var jsn = '{"header-v1":{"archives":{"is_author":"all"}},"header-v4":{"archives":{"is_author":"all"}}}';
This object is constantly updated and I want to remove duplicate values. For example, if it is:
var jsn = '{"header-v4":{"archives":{"is_author":"all"}}}';
And if the new rule set which should be added will be equal to
"header-v1":{"archives":{"is_author":"all"}}
then I want to remove "header-v4":{"archives":{"is_author":"all"}} from there, because there is a duplicate of {"archives":{"is_author":"all"}}.
Is that even possible with JavaScript?
var result = [];
$.each(subservices, function (i, e) {
var matchingItems = $.grep(result, function (item) {
return item.name === e.name && item.label === e.label;
});
if (matchingItems.length === 0){
result.push(e);
}
});
//displays result [{"name":"hello","label":"world"},{"name":"abc","label":"xyz"}]
alert(JSON.stringify(result));
JS fiddel
http://jsfiddle.net/defujjhp/
Maybe something like this you can do
var jsn = '{"header-v4":{"archives":{"is_author":"all"}}}';
var jsonObject = JSON.parse(jsn);
var newJsn = '{header-v1":{"archives":{"is_author":"all"}}}';
var newJsonObject = JSON.parse(newJsn);
var matchingKey = [];
Object.keys(newJsonObject).forEach(key => {
Object.keys(jsonObject).forEach(nkey => {
if(newJsonObject[key].toString() === jsonObject[nkey].toString()) {
matchingKey.push(nkey);
}
});
});
matchingKey.forEach(mkey => {
delete jsonObject[mkey];
});

how to reindex object start from 0

I have an object output from below code how to set the index start from 0 in js?
Object
3: Object
id: 34
type: 0
var obj = {};
var edited = false;
for (var i = 0; i < $(".list").length; i++) {
var data_id = parseInt($(".list").eq(i).attr('data-id'));
var data_type = parseInt($(".list").eq(i).attr('data-type'));
if ((data_type != 0)) {
edited = true;
} else {
edited = false;
}
if (edited == true) {
obj[i] = {};
obj[i]['id'] = data_id;
obj[i]['type'] = data_type;
}
}
console.log(obj);
Needs more jQuery ?
var arr = $(".list").filter(function() {
return $(this).data('type') != 0;
}).map(function() {
return { id : $(this).data('id'), type : $(this).data('type') };
}).get();
FIDDLE
Actually if you want to start in 0, use another variable and not "i" (which I think is 3 when you use it as index).
var obj = {};
var edited = false;
var obj_idx = 0;
for (var i = 0; i < $(".list").length; i++) {
var data_id = parseInt($(".list").eq(i).attr('data-id'));
var data_type = parseInt($(".list").eq(i).attr('data-type'));
if ((data_type != 0)) {
edited = true;
} else {
edited = false;
}
if (edited == true) {
obj[obj_idx] = {};
obj[obj_idx]['id'] = data_id;
obj[obj_idx]['type'] = data_type;
obj_idx += 1;
}
}
console.log(obj);
I think this time obj will be something like:
Object
0: Object
id: 34
type: 0
you could fake object as array by Array.prototype.push.call, in that way you could also gain the side effect: obj.length. it's kinda ninja and elegant :]
var obj = {};
var edited = false;
for (var i = 0; i < $(".list").length; i++) {
var data_id = parseInt($(".list").eq(i).attr('data-id'));
var data_type = parseInt($(".list").eq(i).attr('data-type'));
if ((data_type != 0)) {
edited = true;
} else {
edited = false;
}
if (edited == true) {
Array.prototype.push.call(obj, {id: data_id, type: data_type});
}
}
I am going to give a very simple and readable example. Say you've got an object with the following structure:
Object
0: Object
key: 'some-key'
value: 'some-value'
1: Object
...
Then you might want to delete an entry from it and reindex the whole thing, this is how I do it:
// obj is Object from above
const reIndexed = Object.entries(obj).map((element, index) => {
if (parseInt(element[0] != index) {
element[0] = index.toString();
}
return element;
});

Trouble iterating through an object

I have an object that looks like this:
salesDetails:{ "1":{
"date":"06/22/2014",
"amount":"45",
"currency":"CAD",
"productID":"23",
"status":1},
"2":{
"date":"06/22/2014",
"amount":"120",
"currency":"USD",
"productID":"23",
"status":1},
"3":{
"date":"06/23/2014",
"amount":"100",
"currency":"USD",
"productID":"21",
"status":2},
"4":{
"date":"06/23/2014",
"amount":"250",
"currency":"CAD",
"productID":"25",
"status":1},
"5":{
"date":"06/23/2014",
"amount":"180",
"currency":"USD",
"productID":"24",
"status":1}
}
What i am trying to do is to get all the amount per currency of all that has status of "1" and put it in an object that should look like this:
perCurrency: {
"CAD":{
"0":"45",
"1":"250"},
"USD":{
"0":"120",
"1":"180"}
}
I was able to put all the currency in an object but I'm having trouble with the amount, the last amount from the object overlaps the previous one. I keep on getting {"CAD":{"1":"250"},"USD":{"1":"180"}} Here's my code so far.
function countPerCurrency(){
var currencyArray = new Array();
var perCurrency = {};
var totalSales = Object.size(salesDetails);
for(var i=1; i <= totalSales; i++){
var currency = salesDetails[i]["currency"];
var amount = salesDetails[i]["amount"];
var status = salesDetails[i]["status"];
var totalCurrency = Object.size(currencyAmount[currency]);
var currencyCtr = {};
if(status == 1){
if(!inArray(currency, currencyArray)){
currencyArray.push(currency);
currencyCtr[totalCurrency] = amount;
perCurrency[currency] = currencyCtr;
} else {
var currencyAdd = {};
currencyAdd[totalCurrency] = amount;
perCurrency[currency] = currencyAdd;
}
}
}
}
I know it might seem easy, but I'm lost here.. TIA! :)
The previously accepted answer uses an array of values, whereas you asked for an object. Here's an object version:
var perCurrency = {};
var currencyCount = {};
Object.keys(salesDetails).forEach(function(key) {
var obj = salesDetails[key];
var currency;
if (obj.status == 1) {
currency = obj.currency;
// If this is first for this currency, add it to objects
if (!currencyCount[currency]) {
currencyCount[currency] = 0;
perCurrency[currency] = {};
}
// Add currency values
perCurrency[currency][currencyCount[currency]++] = obj.amount;
}
});
BTW, this has nothing to do with jQuery.
Note that Object.keys is ES5 so may need a polyfill for older browsers, see MDN:Object.keys for code.
try something like this
function countPerCurrency(){
var perCurrency = {};
var totalSales = Object.size(salesDetails);
for(var i=1; i <= totalSales; i++){
var currency = salesDetails[i]["currency"];
var amount = salesDetails[i]["amount"];
var status = salesDetails[i]["status"];
if(status == '1'){
if(perCurrency.hasOwnProperty(currency)){
// if currency already present than get currency array.
var currency_arr = perCurrency[currency];
// add new value to existing currency array.
currency_arr.push(amount);
}else{
// if currency not present than create currency array and add first value;
var currency_arr = [];
currency_arr.push(amount);
// add newly created currency array to perCurrency object
perCurrency[currency] = currency_arr;
}
}
}
console.log(perCurrency);
}
output
perCurrency: {
"CAD":["45","250"],
"USD":["120","180"],
}
I have created currency array instead of key value pair
Change your code like this, i have simplified your things,
function countPerCurrency() {
var perCurrency = {};
var currencyArray = [];
for(i in salesDetails)
{
if(!perCurrency.hasOwnProperty(salesDetails[i].currency) && salesDetails[i].status === "1")
perCurrency[salesDetails[i].currency] = [];
if(salesDetails[i].status === "1")
{
currencyArray = perCurrency[salesDetails[i].currency];
currencyArray.push(salesDetails[i].amount);
perCurrency[salesDetails[i].currency] = currencyArray;
}
}
}
sorry for the late conversation anyway try like this use .each()
var CAD = new Array();
var USD = new Array();
$.each(salesDetails, function (i, value) {
if (value.status == 1) {
if (value.currency == "CAD") {
CAD.push(value.amount);
} else if (value.currency == "USD") {
USD.push(value.amount);
}
}
});
var perCurrency = {
"CAD": CAD,
"USD": USD
}
Demo

Dynamically building array, appending values

i have a bunch of options in this select, each with values like:
context|cow
context|test
thing|1
thing|5
thing|27
context|beans
while looping through the options, I want to build an array that checks to see if keys exist, and if they don't they make the key then append the value. then the next loop through, if the key exists, add the next value, comma separated.
the ideal output would be:
arr['context'] = 'cow,test,beans';
arr['thing'] = '1,5,27';
here's what i have so far, but this isn't a good strategy to build the values..
function sift(select) {
vals = [];
$.each(select.options, function() {
var valArr = this.value.split('|');
var key = valArr[0];
var val = valArr[1];
if (typeof vals[key] === 'undefined') {
vals[key] = [];
}
vals[key].push(val);
});
console.log(vals);
}
Existing code works by changing
vals=[];
To
vals={};
http://jsfiddle.net/BrxuM/
function sift(select) {
var vals = {};//notice I made an object, not an array, this is to create an associative array
$.each(select.options, function() {
var valArr = this.value.split('|');
if (typeof vals[valArr[0]] === 'undefined') {
vals[valArr[0]] = '';
} else {
vals[valArr[0]] += ',';
}
vals[valArr[0]] += valArr[1];
});
}
Here is a demo: http://jsfiddle.net/jasper/xtfm2/1/
How about an extensible, reusable, encapsulated solution:
function MyOptions()
{
var _optionNames = [];
var _optionValues = [];
function _add(name, value)
{
var nameIndex = _optionNames.indexOf(name);
if (nameIndex < 0)
{
_optionNames.push(name);
var newValues = [];
newValues.push(value);
_optionValues.push(newValues);
}
else
{
var values = _optionValues[nameIndex];
values.push(value);
_optionValues[nameIndex] = values;
}
};
function _values(name)
{
var nameIndex = _optionNames.indexOf(name);
if (nameIndex < 0)
{
return [];
}
else
{
return _optionValues[nameIndex];
}
};
var public =
{
add: _add,
values: _values
};
return public;
}
usage:
var myOptions = MyOptions();
myOptions.add("context", "cow");
myOptions.add("context","test");
myOptions.add("thing","1");
myOptions.add("thing","5");
myOptions.add("thing","27");
myOptions.add("context","beans");
console.log(myOptions.values("context").join(","));
console.log(myOptions.values("thing").join(","));
working example: http://jsfiddle.net/Zjamy/
I guess this works, but if someone could optimize it, I'd love to see.
function updateSiftUrl(select) { var
vals = {};
$.each(select.options, function() {
var valArr = this.value.split('|');
var key = valArr[0];
var val = valArr[1];
if (typeof vals[key] === 'undefined') {
vals[key] = val;
return;
}
vals[key] = vals[key] +','+ val;
});
console.log(vals);
}
Would something like this work for you?
$("select#yourselect").change(function(){
var optionArray =
$(":selected", $(this)).map(function(){
return $(this).val();
}).get().join(", ");
});
If you've selected 3 options, optionArray should contain something like option1, option2, option3.
Well, you don't want vals[key] to be an array - you want it to be a string. so try doing
if (typeof vals[key] === 'undefined') {
vals[key] = ';
}
vals[key] = vals[key] + ',' + val;

Categories

Resources