HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Finding subtuple in larger collection?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
subtuplelargercollectionfinding

Problem

I've got a flat array of

  • Readability. I can break this down into smaller methods, but it's essentially a utility function in a much larger class. I guess I could extract it into its own class, but that feels like overkill as well. As-is, it's just too long for me to grok the whole thing in one pass.



public int[] findIndices(final Object[] toSearch, final Object[] toFind) 
{
    Object first = toFind[0];

    List possibleStartIndices = new ArrayList();
    int keyListSize = toFind.length;
    for (int i = 0; i <= toSearch.length - keyListSize; i++) 
    {
        if (first.equals(toSearch[i])) 
        {
            possibleStartIndices.add(i);
        }
    }

    int[] indices = new int[0];
    for (int startIndex : possibleStartIndices) 
    {
        int endIndex = startIndex + keyListSize;
        Object[] possibleMatch = Arrays.copyOfRange(toSearch, startIndex, endIndex);
        if (Arrays.equals(toFind, possibleMatch)) {
            indices = toIndexArray(startIndex, endIndex);
            break;
        }
    }
    return indices;
}

private int[] toIndexArray(final int startIndex, final int endIndex) 
{
    int[] indices = new int[endIndex - startIndex];
    for (int i = 0; i < indices.length; i++)
        indices[i] = startIndex + i;

    return indices;
}

Solution

Here is an O(mn) solution. Given that haystack is about 1000 in length and needle is 5 or smaller, the simplest code to do the search is probably the best. But if testing for equality is expensive, there are things we can do to mitigate that, although I'm not sure switching to KMP or BM will help so much given that we're dealing with Object here.

// assumes no null entries
// returns starting index of first occurrence of needle within haystack or -1
public int indexOf(final Object[] haystack, final Object[] needle) 
{
    foo: for (int a = 0; a < haystack.length - needle.length; a++) {
        for (int b = 0; b < needle.length; b++) {
            if (!haystack[a+b].equals(needle[b])) continue foo;
        }
        return a;
    }
    return -1;
}

Code Snippets

// assumes no null entries
// returns starting index of first occurrence of needle within haystack or -1
public int indexOf(final Object[] haystack, final Object[] needle) 
{
    foo: for (int a = 0; a < haystack.length - needle.length; a++) {
        for (int b = 0; b < needle.length; b++) {
            if (!haystack[a+b].equals(needle[b])) continue foo;
        }
        return a;
    }
    return -1;
}

Context

StackExchange Code Review Q#278, answer score: 5

Revisions (0)

No revisions yet.