Functional programming javascript find in list - javascript

I want to get the first element in a array that matchs a function in O(n) using functional (maybe pure) style. Note im using the functional.js library, but its not that important.
Code to REFACTOR to a pure functional way:
var result = fjs.first(function(value){
return value.id == notification.id;
},array);
I want to refactor it by extracting out the .id for both objects and pass in the notification object, right now its in above scope
So i tried to first map then find. But its super ugly (in my opinion).
var equal = fjs.curry(function(arg1, arg2){ // curry allows for partial functions... i think...
return arg1 == arg2
});
var equalNotificationId = fts.equal(notification.id); // partial function of equal for notification.id number
var newIdArray = fts.map(fts.prop("id"),array);
var result = fts.first(equalNotificationId , newIdArray );
Im looking to refactor this functionaly maybe as pure as possible? Is there a better way?

I found a way to refactor it but if anyone has anything else to bring to this ill give them the points.
//example data
var notification = {id:10};
var array = [{id:11},{id:6},{id:10},{id:3},{id:1}];
//equal function
var equal = fts.curry(function(arg1,arg2){
return arg1 == arg2;
});
//returns object in array with id 10.
var result = fjs.first(fts.compose(equal(notification.id),fts.prop("id")),array);

Related

What is the difference between using document.getElementByID and document.form?

I am trying to teach myself javascript through simple programming ideas. I tasked myself to make a way to calculate two numbers and provide a total of the results by option of using any of the four available operators. It's sort of a very simple calculator, to get to the point. I don't think I need to copy my html code - so I just posted my javascript.
Since I am new to programming in general and javascript, I looked around the web and found some code pointers.
<script>
function add() {
var entry1 = document.getElementById("entry1").value;
var entry2 = document.getElementById("entry2").value;
var sum = Number(entry1)+Number(entry2);
document.getElementById("results").value=sum
}
function sub() {
var entry1 = document.form.entry1.value;
var entry2 = document.form.entry2.value;
var sum = Number(entry1)-Number(entry2);
document.form.results.value=sum
}
function multi() {
var entry1 = document.form.entry1.value;
var entry2 = document.form.entry2.value;
var sum = Number(entry1)*Number(entry2);
document.getElementById("results").value=sum
}
function div() {
var entry1 = document.form.entry1.value;
var entry2 = document.form.entry2.value;
var sum = Number(entry1)/Number(entry2);
document.getElementById("results").value=sum
}
</script>
I think this gives you insight into what I am playing around with. I thought it was interesting I found a way to get around using document.getElementByID, but I guess what I am trying to understand is how you can using both ways...the document.form... and document.getElementById.
Using "document.getElementById" will search the whole DOM looking for "entry1." "Form" in "document.form" refers to the form that encapsulates the whole contents in the <body> tag. As a theory, I did a <div name="blah"> tag in front of <form name="form"> to see if it would use "blah" if I changed document.form to document.blah...it broke. Same thing happened when I tried document.blah.form.entry1....). I think you can see what I am getting at.
I am just curious as to why document.form.entry1.value; works like document.getElementById("entry1").value;?
As others have mentioned,document.getElementById is to be used to select a specific element regardless of what it is. document.forms is to be used to specifically target forms and their elements.
I think document.form points the specific form named or id'ed as the identifier "form" like <form name="form" id="form">.
Please check the syntax document.forms instead of document.<an_identifier> carefully.
document.<an_identifier> may be a dialect of IE.
it's just a kind of syntactic sugar as for me.
Where have you found that "funny" sample? Let me refactor it a bit. hope it will help you better understand to main idea.
<script>
function add(a,b) {
return Number(a) + Number(b);
}
function sub(a,b) {
return Number(a) - Number(b);
}
function multi(a,b) {
return Number(a) * Number(b);
}
function div(a,b) {
return Number(a) / Number(b);
}
function main () { //as an entry point;
var entry1 = document.getElementById('entry1').value,
entry2 = document.getElementById('entry2').value;
$results = document.getElementById("results");
$results.value = add (entry1, entry2);
//$results.value = sub (entry1, entry2);
//$results.value = multi (entry1, entry2);
//$results.value = div (entry1, entry2);
}
</script>
btw: even functions are redundant, but OK I left them as is.
enjoy to JS world

I want object keys to check for duplicates, but I also want to sort the objects later, what should I do?

I have an array called newposts
I itterate through it and if it meets certain criteria, I add it to another array:
for (newpost in newposts){
if (!( newposts[newpost][0] in currentposts )){
var triploc1 = locations[newposts[newpost][1]].location;
var triploc2 = locations[newposts[newpost][2]].location;
var detour_distance = fourpoint_distance(newloc1, triploc1, triploc2, newloc2);
if (worthwhile_detour(original_distance,detour_distance)){
currentposts.push(posts[newposts[newpost][0]])
}
}
}
The second row, is intended to check for duplicates(newposts[newpost][0]) is an ID. When I wrote it I had forgotten that currentposts was an array. Obviously, this doesn't work. I need currentposts to be an array, because just below i sort it. I could ofcourse convert it into an array once the selection is done. But I'm new to javascript and believe someone might know a better way to do this.
function sortposts(my_posts){
my_posts.sort(function(a, b) {
var acount = a.sortvar;
var bcount = b.sortvar;
return (bcount-acount);
});
}
I'm not exactly sure what your desired goal here is, but I can try and clean this up for you. Please note that I'm using the underscore.js library as it makes working with arrays a HECK OF A LOT easier :) If you can't include underscore.js into your project, let me know and I'll write it in "pure" javascript :)
_.each(newposts, function(item) {
if ( _.indexOf(currentposts, posts[item[0]]) >= 0 ) {
var triploc1 = locations[item[1]].location;
var triploc2 = locations[item[2]].location;
var detour_distance = fourpoint_distance(newloc1, triploc1, triploc2, newloc2);
if (worthwhile_detour(original_distance, detour_distance)){
currentposts.push(posts[item[0]])
}
}
});
_.sortBy(currentposts, function(item) {
return item.sortvar;
});
I have to question, however, why you're using so many arrays (newposts, locations, posts, etc)? Are they all needed?

javascript - coldfusion - working with a list

This is probably easy for someone.
I am returning a list of campaignIDs (12,45,66) via JSON to a javascript variable
var campaignList = res.DATA.CAMPAIGNS
Now, given a specified campaignID passed in the URL
var campaignId ='<cfoutput>#url.campaignID#</cfoutput>'
I want to check if the returned list contains this campaignID
Any help much appreciated.
Plenty of ways to do it, but I like nice data structures, so ...
Split the list on comma, then loop over list, looking for value:
function campaignExists(campaignList,campaignId) {
aCampaignList = campaignList.split(',');
for (i=0;i<aCampaignList.length;i++) {
if (aCampaignList[i]==campaignId)
return true;
}
return false;
}
Since Array.indexOf sadly isn't cross browser, you're looking at something like:
// assume there is no match
var match_found = false;
// iterate over the campaign list looking for a match,
// set "match_found" to true if we find one
for (var i = 0; i < campaignList.length; i += 1) {
if (parseInt(campaignList[i]) === parseInt(campaignId)) {
match_found = true;
break;
}
}
If you need to do this repeatedly, wrap it in a function
Here's a bit of a "out of the box" solution. You could create a struct for your property id's that you pass into the json searilizer have the key and the value the same. Then you can test the struct for hasOwnProperty. For example:
var campaignIDs = {12 : 12, 45 : 45, 66 : 66};
campaignIDs.hasOwnProperty("12"); //true
campaignIDs.hasOwnProperty("32"); //false
This way if the list is pretty long you wont have to loop through all of the potential properties to find a match. Here's a fiddle to see it in action:
http://jsfiddle.net/bittersweetryan/NeLfk/
I don't like Billy's answer to this, variables within the function have been declared in the global scope and it is somewhat over complicated. If you have a list of ids as a string in your js just search for the id you have from user input.
var patt = new RegExp("(^|,)" + campaignId + "(,|$)");
var foundCampaign = campaignList.search(patt) != -1;

How to turn this JavaScript string "myArray[0].myPrice" in to a reference to myPrice?

If I have a string of "myArray[0].myPrice", how do I turn this in to a reference to myPrice?
This is the code context:
binding.value = convert(binding.data[binding.field],
binding.converter, binding.data, elem);
binding.field is what contains "myArray[0].myPrice".
binding.data has a reference to the hierarchical object which has an Array property of myArray, and the first element is an object with a property of myPrice.
EDIT: based on the answers, this worked:
binding.value = convert(eval('(binding.data.' + binding.field + ')'),
binding.converter, binding.data, elem);
Is it good to use eval like this? I thought eval was going away in newer JavaScript?
You can use eval, but here is a better solution:
// The following code results in the same as that scary eval(...)
var data = binding.data,
chain = binding.field.split(/[\.\[\]]+/);
for (var i = 0; data[chain[i]]; i++) {
data = data[chain[i]];
}
// Embrace JavaScript Awesomeness!
A breakdown of what I'm doing here:
In JS any property can be called as object[propertyName].
That includes arrays, i.e. a[3] is the same as a['3'].
Therefore, we split the string using one of the characters: ., [, ]. The + is there because without it if you have a[3].b[3] the ]. will give you an empty
string.
We might get an empty string in the end, but that's not a problem since "" is like false in JS.
You could go further and filter out all the invalid variable names, which in javascript is a name that does not conform to [a-zA-Z_$][0-9a-zA-Z_$]*. But I am not quite sure as to why one would do that...
Well, it ain't exactly pretty, but it doesn't use eval:
var str = 'myArray[0].myPrice';
var parts = str.split(/[\[\].]+/);
doSomething(window[parts[0]][parts[1]][parts[2]]);
where window[parts[0]][parts[1]][parts[2]] is the actual reference. Not sure why you'd have a string version and one loaded into memory, though.
Depending on the current context, this might work:
eval("myArray[0].myPrice")
try
var a = eval("myArray[0].myPrice".split('.')[1]);
However this will probably not work in the context you run it in since myPrice will be referring to window.myPrice which I doubt would be defined as anything.
Your best bet here is to define myArray in a scope that can be accessed from anywhere (such as window.AppNS.Data.myArray) and then use the eval() function to access this.
var a = eval("window.AppNS.Data." + "myArray[0].myPrice")
alert(a) // the contents of myPrice are revealed
Here is something similar to the logic we use in the template engine pure.js
var obj = {
myArr:[
{price:15}
],
anObj:{
prop:'ABC'
}
};
function getRef(o, path){
var props = path.split(/\./),
prop,
isArr = /([^\[]+)(\[(\d+)\])*/,
i = 0, ii = props.length;
while(i < ii){
prop = props[i].match(isArr);
o = o[prop[1]];
if(prop[2]){
o = o[+prop[3]];
}
i++;
}
return o;
}
console.log(getRef(obj, 'myArr[0].price')); // --> 15
console.log(getRef(obj, 'anObj.prop')); // --> ABC

What's a good JavaScript pattern for categorizing things into types?

I'm looking for a way (in JavaScript) to collect a set of objects into multiple arrays, where each array contains a certain type of object, and the arrays are stored as values in an associative array, with the keys being the types. For example:
Input:
[<apple>, <cat>, <pear>, <mercedes>, <dog>, <ford>, <orange>]
Output:
{
'fruit': [<apple>, <pear>, <orange>],
'animal': [<cat>, <dog>],
'car': [<mercedes>, <ford>]
}
In ruby, you could do the following:
things_by_type = {}
things.each do |thing|
(things_by_type[thing.type] ||= []) << thing
end
which is nice and concise.
What's a good pattern for doing the same thing in JavaScript that's concise and efficient? I could do something like this, but it's not as nice:
var thing, things_by_type = {};
for (var i = 0; i < things.length; i++) {
thing = things[i];
if(things_by_type[thing.type]) {
things_by_type[thing.type].push(thing);
} else {
things_by_type[thing.type] = [thing];
}
}
I'm not sure if it's a good pattern, but it's similar to your ruby sample:
var things_by_type = {};
for (var i in things) {
var thing = things[i];
(things_by_type[thing.type] || (things_by_type[thing.type] = [])).push(thing);
}
And if you can assume Javascript 1.6:
var things_by_type = {};
things.forEach(function(thing) {
(things_by_type[thing.type] || (things_by_type[thing.type] = [])).push(thing);
})
In ruby, you could do the following:
things_by_type = {}
things.each do |thing|
(things_by_type[thing.type] ||= []) << thing
end
which is nice and concise.
Actually, you can make that even nicer.
First off, Hash.new takes a block argument which will be called every time a non-existing key is referenced. You can use that to create that key. That way you get rid of the conditional logic inside the block.
things_by_type = Hash.new {|h, k| h[k] = [] }
things.each do |thing|
things_by_type[thing.type] << thing
end
Secondly, what you have here is called a fold or reduce: you are "folding" or "reducing" a collection (the array of objects) into a single value (the hash, which confusingly also happens to be a collection, but is nonetheless a single value).
You can generally easily spot this pattern by looking for places where you initialize some variable, then loop over a collection and manipulate that variable at every iteration of the loop.
Ruby has folding built in, via the Enumerable#reduce method:
things.reduce(Hash.new {|h, k| h[k] = [] }) do |h, thing|
h.tap { h[thing.type] << thing }
end
But what you are really doing, is grouping the array by the type attribute of its elements, which is also built into Ruby as Enumerable#group_by:
things.group_by {|thing| thing.type }
Which can be further simplified by using Symbol#to_proc to
things.group_by(&:type)
Unfortunately, ECMAScript doesn't have groupBy, nor default values for non-existing properties, but it does have Array.prototype.reduce:
things.reduce(function (acc, thing) {
(acc[thing.type] || (acc[thing.type] = [thing])).push(thing);
return acc;
}, {});
almost the same code, but works a bit different, you can use the fancy set function easier and it separates logic:
var a = {set:function(type,thing){
if (this[type]) {
this[type].push(thing);
} else {
this[type] = [thing];
}
}};
a.set('a',0);
a.set('b',1);
a.set('a',2);

Categories