Merge two intersecting arrays into a HashMap, One Key & Multiples values - javascript

I'm trying to make a basic calendar to help automate Timesheets at work using Angular.js and Chrome Extensions, but for now I am stuck on this part.
Below you can see two arrays: pastTwoWeeks which is a list of dates from today back 14 days and Timesheet entries which were retrieved from an API - these will actually be objects with many properties but for now I am just using a simple date.
Here's a jsfiddle, am I on the right track? Thanks
http://jsfiddle.net/v599n/
var pastTwoWeeks = ['15/10/2013', '14/10/2013', '13/10/2013',
'12/10/2013', '11/10/2013', '10/10/2013',
'09/10/2013', '08/10/2013', '07/10/2013',
'06/10/2013', '05/10/2013', '04/10/2013',
'03/10/2013', '02/10/2013'];
var entries = ['11/10/2013', '11/10/2013', '11/10/2013',
'11/10/2013', '10/10/2013', '10/10/2013', '10/10/2013',
'09/10/2013', '09/10/2013', '09/10/2013', '08/10/2013',
'08/10/2013', '07/10/2013', '07/10/2013', '04/10/2013',
'04/10/2013', '03/10/2013', '03/10/2013', '02/10/2013',
'02/10/2013', '02/10/2013', '02/10/2013', '01/10/2013',
'01/10/2013', '01/10/2013'];
var calander = {};
for(var j=0; j< pastTwoWeeks.length; j++) {
var key = pastTwoWeeks[j];
if (key in calander == false) {
calander[key] = {};
}
for(var i = 0; i< entries.length; i++) {
var entry = entries[i];
if(entry === key){
calander[key][entry];
console.log(key + " " + entry);
}
}
}
What I want to achieve:
15/10/2013
14/10/2013
13/10/2013
12/10/2013
11/10/2013 (4 entries)
11/10/2013
11/10/2013
11/10/2013
11/10/2013
etc...

Here's a jsfiddle, am I on the right track?
Not really.
calander[key] = {};
I think you rather want an array of entries here, not an object.
calander[key][entry];
This does not do anything. If you were trying to create a property, you would need to assign to it. Also, since all entrys are the same for a key, you would only overwrite the one and same property. Better .push() to an array.
for(var j=0; j< pastTwoWeeks.length; j++) {
for(var i = 0; i< entries.length; i++) {
if(entry === key)
That's rather inefficient. You can do better by executing the loops after each other, and just check whether your entry exists as a key of your calender which was previously filled with the pastTwoWeeks.
var calendar = {};
for (var i=0; i<pastTwoWeeks.length; i++) {
var key = pastTwoWeeks[i];
calendar[key] = [];
}
for (var i=0; i<entries.length; i++) {
var entry = entries[i],
key = entry; // this might change for more complex objects
if (key in calendar) {
calendar[key].push(entry);
console.log(entry+" added to calendar at " + key);
}
}

Something like this should do what your looking for:
var pastTwoWeeks = ['15/10/2013', '14/10/2013', '13/10/2013', '03/10/2013', '02/10/2013'];
var entries = ['11/10/2013', '11/10/2013', '11/10/2013', '01/10/2013', '01/10/2013'];
var calander = {};
pastTwoWeeks.forEach(function(date) {
calander[date] = [];
});
entries.forEach(function(date) {
if (calander[date] === undefined) calander[date] = [];
calander[date].push(date);
});

Related

Remove data from an array comparing it to an other array

I am trying to compare the items in "item" array and the copyofOpList array to retrieve the data occurrences in copyofOpList
this is my try:
var _deleteUsedElement1 = function(item) {
for (var i = 0; i < item.length-1; i++){
for (var j = 0; j< $scope.copyofOpList.length-1; j++){
if (item[i].operationCode == $scope.copyofOpList[j].code) {
$scope.copyofOpList.splice(j, 1);
} } } };
$scope.compareArrays = function() {
...Get data from web Service
_deleteUsedElement1(item);
}
the copyofOpList array has 14 elements,and the item array has 2 array
but my code deletes only one occurrence (the first),so please how can I correct my code,to retrieve any occurances in the copyofOpList array comparing to the item array
thanks for help
I'd try to avoid looping inside a loop - that's neither a very elegant nor a very efficient way to get the result you want.
Here's something more elegant and most likely more efficient:
var item = [1,2], copyofOpList = [1,2,3,4,5,6,7];
var _deleteUsedElement1 = function(item, copyofOpList) {
return copyofOpList.filter(function(listItem) {
return item.indexOf(listItem) === -1;
});
};
copyofOpList = _deleteUsedElement1(item, copyofOpList);
console.log(copyofOpList);
//prints [3,4,5,6,7]
}
And since I just noticed that you're comparing object properties, here's a version that filters on matching object properties:
var item = [{opCode:1},{opCode:2}],
copyofOpList = [{opCode:1},{opCode:2},{opCode:3},{opCode:4},{opCode:5},{opCode:6},{opCode:7}];
var _deleteUsedElement1 = function(item, copyofOpList) {
var iOpCodes = item.map(function (i) {return i.opCode;});
return copyofOpList.filter(function(listItem) {
return iOpCodes.indexOf(listItem.opCode) === -1;
});
};
copyofOpList = _deleteUsedElement1(item, copyofOpList);
console.log(copyofOpList);
//prints [{opCode:3},{opCode:4},{opCode:5},{opCode:6},{opCode:7}]
Another benefit of doing it in this manner is that you avoid modifying your arrays while you're still operating on them, a positive effect that both JonSG and Furhan S. mentioned in their answers.
Splicing will change your array. Use a temporary buffer array for new values like this:
var _deleteUsedElement1 = function(item) {
var _temp = [];
for (var i = 0; i < $scope.copyofOpList.length-1; i++){
for (var j = 0; j< item.length-1; j++){
if ($scope.copyofOpList[i].code != item[j].operationCode) {
_temp.push($scope.copyofOpList[j]);
}
}
}
$scope.copyofOpList = _temp;
};

js Array undefined after json declaration

I m new a web developer and i face up the following problem:
"Cannot read property 'length' of undefined"
my code:
var data=();
for(var i;i<parseInt(window.localStorage["numOfInserts"]);i++){
data["category_name"]=localStorage.getItem(("category_name_"+i).toString());
data["category_id"]=localStorage.getItem(("category_id_"+i).toString());
data["provider_name"]=localStorage.getItem(("provider_name_"+i).toString());
data["provider_id"]=localStorage.getItem(("provider_id_"+i).toString());
data["appointment_date"]=localStorage.getItem(("appointment_date_"+i).toString());
data["appointment_time"]=localStorage.getItem(("appointment_time_"+i).toString());
}
$scope.allAppointments=dataArray;
for(var i=0;i<dataArray.length;i++){
$scope.showme[i]=false;
}
After some research I understand that the problem caused to the fact that data is an array but I try to turn it to json, but
var data ={};
gives me the same error as before.
Please Help me
I think this is what you're looking for, see code comments:
// Create an array using []
var data = [];
// Get the count once
var count = parseInt(window.localStorage["numOfInserts"]);
// Be sure to initialize `i` to 0
for (var i = 0; i < count; i++) {
// Create an object to push onto the array, using the information
// from local storage. Note that you don't need toString() here.
// Once we've created the object (the {...} bit), we push it onto
// the array
data.push({
category_name: localStorage.getItem("category_name_"+i),
category_id: localStorage.getItem("category_id_"+i),
provider_name: localStorage.getItem("provider_name_"+i),
provider_id: localStorage.getItem("provider_id_"+i),
appointment_date: localStorage.getItem("appointment_date_"+i),
appointment_time: localStorage.getItem("appointment_time_"+i)
});
}
This does the same thing, it's just more verbose and so could help you understand more clearly what's going on:
// Create an array using []
var data = [];
// Get the count once
var count = parseInt(window.localStorage["numOfInserts"]);
// Be sure to initialize `i` to 0
for (var i = 0; i < count; i++) {
// Create an object to push onto the array
var obj = {};
// Fill it in from local storage. Note that you don't need toString() here.
obj.category_name = localStorage.getItem("category_name_"+i);
obj.category_id = localStorage.getItem("category_id_"+i);
obj.provider_name = localStorage.getItem("provider_name_"+i);
obj.provider_id = localStorage.getItem("provider_id_"+i);
obj.appointment_date = localStorage.getItem("appointment_date_"+i);
obj.appointment_time = localStorage.getItem("appointment_time_"+i);
// Push the object onto the array
data.push(obj);
}
You need to create an array(dataArray before the loop), and create a new object in each iteration and set the property values for that object then add the object to the array like below
var dataArray = [],
data, numOfInserts = parseInt(window.localStorage["numOfInserts"]);
for (var i = 0; i < numOfInserts; i++) {
data = {};
data["category_name"] = localStorage.getItem(("category_name_" + i).toString());
data["category_id"] = localStorage.getItem(("category_id_" + i).toString());
data["provider_name"] = localStorage.getItem(("provider_name_" + i).toString());
data["provider_id"] = localStorage.getItem(("provider_id_" + i).toString());
data["appointment_date"] = localStorage.getItem(("appointment_date_" + i).toString());
data["appointment_time"] = localStorage.getItem(("appointment_time_" + i).toString());
dataArray.push(data)
}
$scope.allAppointments = dataArray;
for (var i = 0; i < dataArray.length; i++) {
$scope.showme[i] = false;
}
It looks like you're trying to create an associative array, so the first line should indeed be
var data = {};
The next part is fine, but then it looks like you want to enumerate the keys
for(var i=0;i<Object.keys(data).length;i++){
$scope.showme[i]=false;
}

How to delete a specific item/object in localStorage?

Turns out that my localStorage["items"] stored my JSON as a string.
"["{\"itemId\":1, \"itemName\":\"item1\"}", "{\"itemId\":2, \"itemName\":\"item2\"}",
"{\"\":3, \"itemName\":\"item3\"}",]"
This is what it looks like when I JSON.parse(localStorage["items"]):
["{"itemId":1, "itemName":"item1"}", "{"itemId":2, "itemName":"item2"}"
"{"itemId":3, "itemName":"item3"}"]
So in my loop I made it into an object by using jQuery.parseJSON:
var object = jQuery.parseJSON(item[i]);
Right now, what I want to do is delete the object where itemId = 3 and make sure that the object is totally removed from the localStorage.
Here's my Javascript so far:
$("#button_delete").on("click", function(e){
e.preventDefault();
var items = JSON.parse(localStorage.getItem('items'));
for (var i = 0; i < items.length; i++) {
var object = JSON.parse(items[i]);
if(object.request_id == 3){
console.log(items)
delete items[i] // slice doesn't work not sure why
console.log(items)
}
}
item = JSON.stringify(items);
console.log(item);
localStorage.setItem('items', item);
})
UPDATED
When I click the button now, it will delete that item however it will not delete the comma before it.
When I check the localStorage["items"] in the browser it returns this:
"["{\"itemId\":1, \"itemName\":\"item1\"}","{\"itemId\":2, \"itemName\":\"item2\"}",null]"
I have another page that will display the info in the html and it returns the error:
Uncaught TypeError: Cannot read property 'itemId' of null.
So right now is there a way to check or search in localStorage["items"] specifically for ,null and remove it so that the error won't show?
Code on how I'm displaying the info in HTML:
var items = JSON.parse(localStorage.getItem('items'));
var itemsHTML = "";
for(var i = 0; i < items.length; i++){
var object = jQuery.parseJSON(items[i]);
var displayItemId = object.itemId;
var displayItemName = object.itemName;
itemsHTML += "<li id="+displayItemId+">"+displayItemName+"</li>";
}
$("#viewItemList").html(itemsHTML);
All the answers were right but you have to :
Parse the string in localStorage to JSON (you did that)
Remove the item you don't want (with slice() )
Make the JSON to string
Re-set it in the localStorage
So :
1.
var items = JSON.parse(localStorage.getItem("items")); // updated
2.
for (var i =0; i< items.length; i++) {
var items = JSON.parse(items[i]);
if (items.itemId == 3) {
items.splice(i, 1);
}
}
3.
items = JSON.stringify(items); //Restoring object left into items again
4.
localStorage.setItem("items", items);
Parsing to JSON and storing it as string is kinda annoying, but that's the way localStorage works.
Try this one.
$("#button_delete").on("click", function(e){
e.preventDefault();
var items = JSON.parse(localStorage["items"]);
for (var i = 0; i < items.length; i++) {
if(items[i].itemId == 3){
items.splice(i,1);
break;
}
}
})
If you know the key of the specific item - do it short and simple like this:
if (localStorage.getItem('key_to_remove') != null)
localStorage.removeItem('key_to_remove');
localstorage can contain strings only
So first you have to parse items from localstorage (like u do now)
Remove from it the element you don't want.
Serialize it to JSON one more time and store in localstorage.
Here is the approach
var items = localStorage["items"];
for (var i =0; i< items.length; i++) {
var item = JSON.parse(items[i]);
if (item.itemId == 3) {
items.slice(i);
break;
}
}
// Don't forget to store the result back in localStorage
localStorage.setItem("items", items);
eliminar(est: string) {
//estudiantes ES LA KEY
var items = JSON.parse(localStorage.getItem('estudiantes'));
for (var i = 0; i < items.length; i++) {
var item = items[i];
if(item.id == est){
items.splice(i,1);
}
}
items = JSON.stringify(items);
localStorage.setItem('estudiantes', items);
this.getAll();
}

Objects within an Array

I have multiple objects like the one below, and I was wondering what the correct syntax would be for putting them all within a single array. I'm also wondering how to correctly cycle through all of the arrays.
var verbMap = [
{
infinitive: "gehen",
thirdPres: "geht",
thirdPast: "ging",
aux: "ist",
pastPart: "gegangen",
english: "go"
},
{
infinitive: "gelingen",
thirdPres: "gelingt",
thirdPast: "gelang",
aux: "ist",
pastPart: "gelungen",
english: "succeed"
}
];
I know the correct way to cycle through that above array is:
for(v in verbMap){
for(p in verbMap[v]){
}
}
If I wanted to cycle through a larger array holding multiple arrays like verbMap, what would be the correct way to do that?
Just put the verbMap arrays in another array.
var verbMaps = [verbMap1, verbMap2...]
The key thing to understand is that your verbMap is an array of object literals. Only use
for (k in verbMap)...
for object literals.
The correct way to loop thru an array is something like
for (var i = 0; i < verbMaps.length; i++) {
var currentVerbMap = verbMaps[i];
for (var j = 0; j < currentVerbMap.length; j++) {
var currentHash = currentVerbMap[j];
for (var k in currentHash) {
console.log(k, currentHash[k];
}
}
}
The following function outputs every value from a (possibly) infinite array given as a parameter.
function printInfiniteArray(value){
if (value instanceof Array){
for(i=0;i<value.length;i++){
printInfiniteArray(value[i]);
}
} else {
console.log(value);
}
}
Edited code. Thanks jtfairbank
Your array does not contain other arrays. It contains objects. You could try this to loop though it.
for(var i = 0; i < verbMap.length; i++)
{
var obj = verbMap[i];
alert("Object #"+ i " - infinitive: " + obj.infinitive);
}
You would treat the array like any other javascript object.
var arrayOfArrays = [];
var array1 = ["cows", "horses", "chicken"];
var array2 = ["moo", "neigh", "cock-adoodle-doo"];
arrayOfArrays[0] = array1;
arrayOfArrays[1] = array2;
You can also use javascript's literal notation to create a multi-dimentional array:
var arrayOfArrays = [ ["meat", "veggies"], ["mmmm!", "yuck!"] ];
To cycle through the array of arrays, you'll need to use nested for loops, like so:
for (var i = 0; i < arrayOfArrays.length; i++) {
var myArray = arrayOfArrays[i];
for (var j = 0; j < myArray.length; j++) {
var myData = myArray[0]; // = arrayOfArrays[0][0];
}
}
DO NOT USE For...in!!!
That is not what it was made for. In javascript, For...in can have some unwanted behaviors. See Why is using "for...in" with array iteration a bad idea? for more detail.
You can use jQuery.each to cycle through an array or object, without having to check which one it is. A simple recursive function to cycle through key-value pairs in a nested structure, without knowing the exact depth:
var walk = function(o) {
$.each(o, function(key, value) {
if (typeof value == 'object') {
walk(value);
} else {
console.log(key, value);
}
});
}

How do I push the keys from an object to an array?

Suppose I have the following object obj:
obj = {
'key1' : ['1','2','3'],
'key2' : ['1','2','9'],
'key3' : ['1','3','5']
}
How can I transform obj into two arrays that look like the following?
allOfTheKeys = ['key1','key2','key3']
allOfTheArrays = ['1','2','3','5','9']
Something like
allKeys = [];
allElems = [];
for(var k in obj){
allKeys.push(k);
for(var e in obj[k]){
allElem.push(e)
}
}
Actually, in jQuery you can do it more concisely using each() (warning, this isn't tested code):
jQuery.each(obj,function(key){
allKeys.push(key);
jQuery.each(obj[key],function(elem){
allElems.push(elem);
}
});
Okay, you don't want repeats, add in
if(!(elem in allElems)) allElems.push(elem);
As I saw, other answers return repeated values. Here you have the solution (tested):
var allOfTheKeys = [], allOfTheArrays = [], nonRepeatedElems = {};
for(var key in obj){
allOfTheKeys.push(key);
for(var i=0; i< obj[key].length; i++)
nonRepeatedElems[obj[key][i]] = true;
}
for(var e in nonRepeatedElems )
allOfTheArrays.push(e);
If someone's wondering what nonRepeatedElems is, it's a hash table for the array values, whose key is the array element value. So I don't get repeated elements.
If you want your values to be ordered, just call allOfTheArrays.sort(); in the end.
EDIT: #float, Here you have a more understandable solution:
var allOfTheKeys = [], allOfTheArrays = [];
for(var key in obj){
allOfTheKeys.push(key);
for(var i=0; i< obj[key].length; i++){
var arrayElem = obj[key][i];
if(!$.inArray(arrayElem, allOfTheArrays)) //Add to the array if it doesn't exist yet
allOfTheArrays.push(arrayElem);
}
}

Categories

Resources