Thursday, 10 July 2014

CFML: This always trips people up: the difference between listContains() and listFind()

G'day:
This question came in via email. Fortunately (given my reaction the other day "I'm not Ben Nadel (or Ray Camden)") this one was suggesting a blog article, and a blog article it shall receive. The email was about listContains(), as is as follows:

I just wanted to throw this out there for you as a possible blog post if you’re interested. I was working on some code which I was running through an array of structures. Anyhow, as I loop the structure, I have an if condition ListContainsNoCase(“label,fieldtype”,KEY). One of the keys is “type” which was causing the dynamic form not to display correctly. When I remove the “fieldtype” from the list, the form works. I was removing “fieldtype” so that it’s not an attribute of the field. I thought it was interesting that it’s looking at the word “type” within “fieldtype” vs. looking at the comma delimited list instead and looking at the word as a whole.
Unfortunately the person here is falling foul of something I think everyone falls foul of... when they're seeing is exactly what's expected, and exactly how listContains() (and listContainsNoCase() works).

Here's what it says in the docs ("listContains()"):

Description

Determines the index of the first list element that contains a specified substring.
And this is what it says about listFind(), by comparison:

Description

Determines the index of the first list element in which a specified value occurs.
So listContains() matches a substring; listFind() matches the whole element.

Here's some demonstration tests to pad the article out:

// TestListContains.cfc
component extends="testbox.system.BaseSpec" {

    function beforeAll(){
        variables.list = "tahi,rua,toru,wha";
    }

    function run(){
        describe("Tests for listContains()", function(){
            it("finds an exact match", function(){
                expect(listContains(list, "tahi")).toBe(1);
            });
            it("finds a partial match", function(){
                expect(listContains(list, "to")).toBe(3);
            });
        });
        describe("Tests for listFind()", function(){
            it("finds an exact match", function(){
                expect(listFind(list, "rua")).toBe(2);
            });
            it("doesn't find a partial match", function(){
                expect(listFind(list, "to")).toBe(0);
            });
        });
    }
}

HTH.

--
Adam