Monday, February 21, 2011

What is the best way to do loops in JavaScript

I have stumbled into several methods of looping in JavaScript, what I like the most is:

for(var i = 0; i < a.length; i++){
    var element = a[i];
}

But as tested here (http://www.robertnyman.com/2008/04/11/javascript-loop-performance/), it should probably be written so that the length is only calculated once.

In jQuery there is a .each that you can stick a function. I like this a little better, because I don't have to type the array twice, like in the above solution.

If JavaScript supported macros it would be a piece of cake to roll your own, but sadly it does not.

So what do you guys use?

From stackoverflow
  • You could just always use a while loop, and compute the array limit before hand.

    Var max = a.length-1;
    var i = 0;
    
    while(i <= max)
    {
    var element = a[i];
    i++;
    }
    
    Anders Rune Jensen : Sorry to be blunt, but I fail to see how this is an improvement. You still specify the array twice, and in your solution the environment around is polluted with two variables which scrope should not transcend the while loop construct.
    Jason Etheridge : The environment is going to be "polluted" anyway, given that in Javascript the scope of a variable is the enclosing function, not the block in which it is declared.
    Kibbee : Testing it against the link given in the question, it's at least as fast, if not faster, than any of the for loop implementations.
  • I've started using iterators where relevant. Performance is reasonable, however more importantly it allows you to encapsulate the looping logic:

    function createIterator(x) {
        var i = 0;
    
         return function(){
           return x[i++];
        };
    }
    

    Then to use:

    var iterator=createIterator(['a','b','c','d','e','f','g']);
    
    iterator();
    

    returns "a";

    iterator();
    

    returns "b";

    and so on.

    To iterate the whole list and display each item:

    var current;
    
    while(current=iterator())
    {
        console.log(current);
    }
    

    Be aware that the above is only acceptable for iterating a list that contains "non-falsy" values. If this array contained any of:

    • 0
    • false
    • ""
    • null
    • NaN

    the previous loop would stop at that item, not always what you want/expect.

    To avoid this use:

    var current;
    
    while((current=iterator())!==undefined)
    {
       console.log(current);
    }
    
    Anders Rune Jensen : Yeah, I have also been thinking about using iterators. They much better encapsulate the concept of traversing something than simple loops do. But how would you in your example print all elements in the iterator?
    Jason Bunting : Beautiful closure sweetness. Ahh, I loves 'em.
    Kibbee : How do you know when you've reached the end if your iterator doesn't have a HasNext function? If you just keep on calling "iterator" per your example, you will eventually get array index out of bounds.
    Ash : Kibbee, Anders, I've added a simple example of how to iterate the whole list to the answer.
    Anders Rune Jensen : Love it. Thanks!
    Kibbee : Sorry, I guess i'm a little to conditioned to using languages that throw exceptions when you try to access past the end of the array to try to code something that relies on the fact that JS doesn't throw an exception when you try to do this.
    Ash : Kibbee, No need to be sorry, I should have added that example earlier. One of the most important things to know in Javascript is the "falsy" values (values that are evaluated as false). These are: "", null, 0, NaN, false and finally undefined. The iterator relies on undefined being returned.
    insin : If you liked this answer, you may be interested in http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/ and Mochikit's http://mochikit.com/doc/html/MochiKit/Iter.html
    Manuel Ferreria : This is rather hackish. Me like it!
    Jani Hartikainen : Welcome to the world of Slow and Confusing. This idiom is *far* from common in JavaScript world, so people will have difficulties with your codebase if you decide to use this. If you have large loops, this approach is also *very* slow. Function calls are expensive in JS.
    Ash : @Jani, welcome to the world of New Ideas! This answer might help make the idiom more common. Also, performance is more than acceptable for normal day to day usage in my experience, and this depends heavily on the Javascript engine running it anyway. Function calls may be expensive, but un-maintainable Javascript costs a hell of a lot more!
    Jani Hartikainen : A "standard" loop is hardly unmaintainable. However I can see you understood my point ;)
  • Small improvement to the original, to only calculate the array size once:

    for(var i = 0, len = a.length; i < len; i++){ var element = a[i]; }
    

    Also, I see a lot of for..in loops. Though keep in mind that it's not technically kosher, and will cause problems with Prototype specifically:

    for (i in a) { var element = a[i]; }
    
    Vincent Robert : for..in loops are used to iterate over object properties, while they seem to work for Arrays, they will also iterate over the 'length' property or any other dynamically added property. That's why it does not work well with Prototype.
  • Just store the length in a variable first.

      var len = a.length;
      for (var i = 0; i < len; i++) {
        var element = a[i];
      }
    
  • And you can see a little test on the issue in: http://stackoverflow.com/questions/157260/whats-the-best-way-to-loop-through-a-set-of-elements-in-javascript#161664

  • If you have many elements in the array and speed is an issue then you want to use a while loop that iterates from highest to lowest.

      var i = a.length;
      while( --i >= 0 ) {
        var element = a[i];
        // do stuff with element
      }
    
    Paul Hargreaves : the >= 0 isn't needed, just change --i to i--
  • I don't use it myself, but one of my colleagues uses this style:

    var myArray = [1,2,3,4];
    for (var i = 0, item; item = myArray[i]; ++i) {
        alert(item);
    }
    

    like Ash's answer, this will hit issues if you've got "falsey" values in your array. To avoid that problem change it to (item = myArray[i]) != undefined

  • I know I'm late to the party, but I use reverse loops for loops that don't depend on the order.

    Very similar to @Mr. Muskrat's - but simplifying the test:

    var i = a.length, element = null;
    while (i--) {
      element = a[i];
    }
    
    annakata : well I'm *very* late to the party, but this is the correct answer and should be accepted as such. For the uninitiated, the i-- clause saves a comparison (because 0 = false in JS tests). Caveat 1: reverse order! Caveat 2: readability isn't great. Caveat 3: a cached for loop is very nearly as good
  • I tried Ash's solution and sadly declaring the two variables is quite tiresome in the end. I'm currently using the .each() from jquery and so far it's the best I have found. The only problem is that one can't return directly from the loop, and that break and continue is implementated as ugly idiosyncrasies (return true/false).

  • http://blogs.sun.com/greimer/entry/best_way_to_code_a

    That basically covers the whole subject

    Anders Rune Jensen : pretty wierd that the "while (i--)" solution is the fastest ;-)
  • So, first you identify the perfect javascript loop, I believe it should look like this:

    ary.each(function() {$arguments[0]).remove();})

    This may require the prototype.js library.

    Next, you get disgustet with the arguments[0] part and have the code be produced automatically from your server framework. This works only if the ladder is Seaside.

    Now, you have the above generated by:

    ary do: [:each | each element remove].

    This comes complete with syntax completion and translates exactly to the above javascript. And it will make people's head spin that haven't used seasides prototype integration before, as they read your code. It sure makes you feel cool, too. Not to mention the gain in geekiness you can get here. The girls love it!

  • I don't see what the problem with using a standard for(;;) loop is. A little test

    var x;
    var a = [];
    // filling array
    var t0 = new Date().getTime();
    for( var i = 0; i < 100000; i++ ) {
        a[i] = Math.floor( Math.random()*100000 );
    }
    
    // normal loop
    var t1 = new Date().getTime();
    for( var i = 0; i < 100000; i++ ) {
        x = a[i];
    }
    
    // using length
    var t2 = new Date().getTime();
    for( var i = 0; i < a.length; i++ ) {
        x = a[i];
    }
    
    // storing length (pollution - we now have a global l as well as an i )
    var t3 = new Date().getTime();
    for( var i = 0, l = a.length; i < l; i++ ) {
        x = a[i];
    }
    
    // for in
    var t4 = new Date().getTime();
    for( var i in a ) {
        x = a[i];
    }
    
    // checked for in
    var t5 = new Date().getTime();
    for( var i in a ) {
        if (a.hasOwnProperty(i)) {
            x = a[i];
        }
    }
    
    var t6 = new Date().getTime();
    var msg = 'filling array: '+(t1-t0)+'ms\n'+
              'normal loop: '+(t2-t1)+'ms\n'+
              'using length: '+(t3-t2)+'ms\n'+
              'storing length: '+(t4-t3)+'ms\n'+
              'for in: '+(t5-t4)+'ms\n'+
              'checked for in: '+(t6-t5)+'ms';
    console.log( msg );
    

    results in:

    filling array: 227ms
    normal loop: 21ms
    using length: 26ms
    storing length: 24ms 
    for in: 154ms
    checked for in: 176ms
    

    So:- for in's take the longest, using the length property (which is a property and doesn't need to be calculated) is nearly as fast as storing it first - which is only a whisker slower than using an integer.
    AND a for() is the usual way to loop over an array, which everyone expects and understands.

    All of them add a variable to the scope they run in - i - which is a common name for this use and so shouldn't be used for other things. Storing the length first adds another var - l - to the scope, which is unnecesary

How do you make php's json_decode compatible with firefox's javascript?

it appears if you have something like

var my_var = {"foo" : "bar"};

in javascript (with firefox at least) and post it to a php server you will receive a string like

{foo:"bar",}

on the server side. But json_decode in php doesn't like the trailing ',' or the lack or quotes around 'foo'. Is there a nice way to clean up the received json string?

The json object is sent with the drupal module json services.

EDIT: This question can be closed. The badly formed json is due to badly written js in the drupal module

From stackoverflow
  • What code are you using to POST the data? Make sure you're using something like json2.js.

    Steven Noble : I should check. I'm using drupal's json_service modulue.
    Steven Noble : Ah, this seems to be the crux of the problem. A badly written json encoder
  • This would be a good way to handle JSON where you can't predict whether there's extraneous commas:

    function json_decode_($json_string) {
        $json_string = preg_replace('/,(\s*)}/s', '$1}', $json_string);
        return json_decode($json_string);
    }
    

    Note, this is untested, but I think it should work.

How to scan a folder in Java?

How can I get a tree of all the files from a current folder in Java?

From stackoverflow
  • import java.io.File;
    public class Test {
        public static void main( String [] args ) {
            File actual = new File(".");
            for( File f : actual.listFiles()){
                System.out.println( f.getName() );
            }
        }
    }
    

    It displays indistinctly files and folders.

    See the methods in File class to order them or avoid directory print etc.

    http://java.sun.com/javase/6/docs/api/java/io/File.html

    Michael Myers : Your anchor link is broken (I guess the markup system assumes parentheses can't be in hyperlinks).
    OscarRyz : Thanks. What about now?
    Lipis : hehe.. I should probably RTFM more often.. :)
    Michael Myers : If you put the link in a footnote, the one you had originally should actually work. (I know because I just did it in a different question.)
    Michael Myers : Actually, just putting angle brackets around it ought to do the trick.
  • Check out Apache Commons FileUtils (listFiles, iterateFiles, etc.). Nice convenience methods for doing what you want and also applying filters.

    http://commons.apache.org/io/api-1.4/org/apache/commons/io/FileUtils.html

  • Not sure how you want to represent the tree? Anyway here's an example which scans the entire subtree using recursion. Files and directories are treated alike. Note that listFiles() returns null for non-directories.

    public static void main(String[] args) {
        final Collection<File> all = new ArrayList<File>();
        addFilesRecursively(new File("."), all);
        System.out.println(all);
    }
    
    private static void addFilesRecursively(File file, Collection<File> all) {
        final File[] children = file.listFiles();
        if (children != null) {
            for (File child : children) {
                all.add(child);
                addFilesRecursively(child, all);
            }
        }
    }
    
    marcospereira : I can't remember how much times I have wrote this code. :-P
    volley : Yeah it's like a recurring nightmare.. :P~
    Lipis : I have to accept this answer since I asked for the tree (I had accepted the Oscar Reyes' answer first).. even though adding one more line for the recursion wasn't that hard :)
  • In JDK7, "more NIO features" should have methods to apply the visitor pattern over a file tree or just the immediate contents of a directory - no need to find all the files in a potentially huge directory before iterating over them.

  • You can also use the FileFilter interface to filter out what you want. It is best used when you create an anonymous class that implements it:

    import java.io.File;
    import java.io.FileFilter;
    
    public class ListFiles {
        public File[] findDirectories(File root) { 
            return root.listFiles(new FileFilter() {
                public boolean accept(File f) {
                    return f.isDirectory();
                }});
        }
    
        public File[] findFiles(File root) {
            return root.listFiles(new FileFilter() {
                public boolean accept(File f) {
                    return f.isFile();
                }});
        }
    }
    

Index of Linq Error

If I have the following Linq code:

context.Table1s.InsertOnSubmit(t);
context.Table1s.InsertOnSubmit(t2);
context.Table1s.InsertOnSubmit(t3);

context.SubmitChanges();

And I get a database error due to the 2nd insert, Linq throws an exception that there was an error. But, is there a way to find out that it was the 2nd insert that had the problem and not the 1st or 3rd?

To clarify, there are business reasons that I would expect the 2nd to fail (I am using a stored procedure to do the insert and am also doing some validation and raising an error if it fails). I want to be able to tell the user which one failed and why. I know this validation would be better done in the C# code and not in the database, but that is currently not an option.

From stackoverflow
  • Comment out the first and third inserts to eliminate them as suspects.

    My first thought is that the second insert has the same ID as the first, but it's tough to diagnose your problem without more details about the error.

    NotDan : See my comments above. I am causing the insert to fail in the SP based on some conditional logic. I just want to know which one is failing.
  • You can specify explicitly a conflict mode like this one :

    context.SubmitChanges(ConflictMode.ContinueOnConflict);
    

    if you want to insert what is valid and not fail on the first conflict, then use the

    context.ChangeConflicts
    

    collection to find out which objects conflicted during the insertion.

What is an efficient way to check the precision and scale of a numeric value?

I'm writing a routine that validates data before inserting it into a database, and one of the steps is to see if numeric values fit the precision and scale of a Numeric(x,y) SQL-Server type.

I have the precision and scale from SQL-Server already, but what's the most efficient way in C# to get the precision and scale of a CLR value, or at least to test if it fits a given constraint?

At the moment, I'm converting the CLR value to a string, then looking for the location of the decimal point with .IndexOf(). Is there a faster way?

From stackoverflow
  • You can use decimal.Truncate(val) to get the integral part of the value and decimal.Remainder(val, 1) to get the part after the decimal point and then check that each part meets your constraints (I'm guessing this can be a simple > or < check)

  • System.Data.SqlTypes.SqlDecimal.ConvertToPrecScale( new SqlDecimal (1234.56789), 8, 2)
    

    gives 1234.67. it will truncate extra digits after the decimal place, and will throw an error rather than try to truncate digits before the decimal place (i.e. ConvertToPrecScale(12344234, 5,2)

    Pittsburgh DBA : 1234.57, but I voted you up anyway, because it's a great answer.

HOWTO: specify in app.config to call a function before Main() is called?

I really want to put in some sort of section handler into App.config that will execute some code before the application actually starts executing at Main. Is there any way to do such a thing?

From stackoverflow
  • Why dont you put that call as the first instruction in your main function?

    Otherwise you can define another entry point for your program and call your main from there but its basicaly the same

  • Not sure what you're trying to accomplish...but, I'm not aware of anyway you can have a console application run any other method before Main(). Why not do something like this:

    static void Main(string[] args)
    {
        //read your app.config variable
        callAlternate = GetConfigSettings(); 
        if(callAlternate)
            AltMain();
    
        ///...rest of Main()
    }
    

Why can't .NET parse a date string with a timezone?

.NET throws an exception trying to parse a datetime string in this format:

Fri, 10 Oct 2008 00:05:51 CST

Convert.ToDateTime("Fri, 10 Oct 2008 00:05:51 CST") results in an exception:

The string was not recognized as a valid DateTime. There is a unknown word starting at index 26

Character 26 obviously being the start of "CST"

In a quick test, PHP and javascript can both parse this string into a date with no problem. Is .NET just full of fail or is there a reasonable explanation?

From stackoverflow
  • http://msdn.microsoft.com/en-us/library/ey1cdcx8.aspx

    You need to use the overloaded DateTime.Parse to accurately parse timezones.

  • If a specific date and time format will be parsed across different locales, use one of the overloads of the ParseExact method and provide a format specifier.