Data Layer Scan

Benchmark created on


Setup

const dataLayer = {
    'foo': {
        'email': 'test_user@gmail.com',
        'baz': {
            'boo': {
                'faz': {
                    'email': 'random_user@gmail.com'
                }
            }
        },
        'user_info': {
            'email': 'my_emaiL@gmail.com'
        }
    }
}

const keysToIgnore = new Set(['items', 'ecommerce']);
const emailRegexp = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i;
const keyRegex = new RegExp('email', 'i');
const validator = (text) => {
    const match = text.match(emailRegexp);
    return match ? match[0].trim().toLowerCase() : undefined;
};
const dfsMaxdepth = 5;
const bfsMaxDepth = 2;

function dfsDataLayer(
    obj,
    path,
    currentDepth = 0
) {
    const result = [];

    if (currentDepth >= dfsMaxdepth) {
        return result;
    }

    const keys = Object.keys(obj);
    for (const key of keys) {
        if (keysToIgnore.has(key)) {
            continue;
        }

        const value = obj[key];
        if (!value) {
            continue;
        }

        const currentPath = currentDepth === 0 ? key : `${path}.${key}`;
        if (typeof value === 'object') {
            const matches = dfsDataLayer(value, currentPath, currentDepth + 1);

            for (const match of matches) {
                result.push(match);
            }
        } else if (keyRegex.test(key)) {
            const data = validator(value);
            if (data) {
                result.push(data);
            }
        }
    }

    return result;
}

function bfsDataLayer(obj, path) {
    const queue = [{
        obj,
        path: '',
        depth: 0
    }]

    while (queue.length > 0) {
        const {
            obj: parentObj,
            path: parentPath,
            depth: parentDepth
        } = queue.shift();

        const keys = Object.keys(parentObj);
        for (const key of keys) {
            if (keysToIgnore.has(key)) {
                continue;
            }

            const value = parentObj[key];
            if (!value) {
                continue;
            }

            const currentPath = parentDepth === 0 ? key : `${parentPath}.${key}`;
            if (typeof value === 'object' && parentDepth + 1 <= bfsMaxDepth) {
                queue.push({
                    obj: value,
                    path: currentPath,
                    depth: parentDepth + 1
                });
            } else if (keyRegex.test(key)) {
                const data = validator(String(value));
                if (data) {
                    return [data];
                }
            }
        }
    }

    return [];
}

dfsResults = dfsDataLayer(dataLayer, '', 0);
console.log(dfsResults);

bfsResults = bfsDataLayer(dataLayer, '');
console.log(bfsResults);

Test runner

Ready to run.

Testing in
TestOps/sec
Initial (DFS, maxDepth=5, full search)
dfsResults = dfsDataLayer(dataLayer, '', 0);
console.log(dfsResults);
ready
Optimized (BFS, maxDepth=2, short circuit)
bfsResults = bfsDataLayer(dataLayer, '');
console.log(bfsResults);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.