Last week I was finishing up some stuff to do with size/color selection on the product detail “page” of the Android app I’m building. This turned out to be pretty complicated. The overall solution is bigger than the scope of this post but basically, the detail page should display all of the colors and sizes available for the product. If the customer selects a color it should filter the other lists, somehow marking the sizes that are sold out for that color. It should do the same thing for sizes, filtering colors if the customer selects a size. It should work exactly like a product detail page on our site does.

This would be easy if every product had common color and size attributes. But we carry everything from kitchenware to tents. So the page needed to be built so that a selection display would be dynamically created for every relevant attribute (color, size, width, inseam, waist, chest, length, etc) and all the selection displays would filter each other.

Once I got that all sorted out I noticed that the displays had their sizes sorted as strings. This meant that sizes would go 10, 11, 12, 6, 7, 8, 9 since 1 comes before 6 in the “alphabet.” So, I needed a way to intelligently sort numbers as numbers and strings as strings. Except that doesn’t work either because XXS, XS, S, M, L, XL, XXL are far from being alphabetical. So, I had to develop a sorting algorithm that could sort shoe sizes, widths (A, B, C, D…) and standard sizes.

What I did was give S, M and L values of -1, 0 and 1 respectively. The number of X’s are multiplied by the value of the size and then ordered by their total value. One other thing I had to deal with is the fact that some things are marked as XXL and others are marked as 2XL. Below is my solution.
This is my dictionary of size values:

private static Dictionary mSizeValues = new Dictionary() {
    {"s", -1},
    {"m", 0},
    {"l", 1}
};

 

Here’s my custom sorting method:

public static int AttributeSort(string x, string y) {

    // sorting for floats (shoe sizes)
    float xFloat;
    bool xIsFloat = float.TryParse(x, out xFloat);
    float yFloat;
    bool yIsFloat = float.TryParse(y, out yFloat);
    if (xIsFloat && yIsFloat) {
        return xFloat.CompareTo(yFloat);
    }

    // sorting for S/M/L (t-shirts, etc)
    x = x.ToLower();
    y = y.ToLower();
    string pattern = "(?<xCount>[0-9]*)(?<xString>x*)(?<size>[sml])$";
    Match xMatch = Regex.Match(x, pattern);
    Match yMatch = Regex.Match(y, pattern);
    if (xMatch.Success && yMatch.Success) {
        int xVal = 1;
        int xXCount;
        xVal = (int.TryParse(xMatch.Groups["xCount"].Value, out xXCount)) ? xVal + xXCount : xVal;
        xVal += xMatch.Groups["xString"].Length;
        xVal = (xMatch.Groups["size"].Success) ? xVal * mSizeValues[xMatch.Groups["size"].Value] : xVal;

        int yVal = 1;
        int yXCount;
        yVal = (int.TryParse(yMatch.Groups["xCount"].Value, out yXCount)) ? yVal + yXCount : yVal;
        yVal += yMatch.Groups["xString"].Length;
        yVal = (yMatch.Groups["size"].Success) ? yVal * mSizeValues[yMatch.Groups["size"].Value] : yVal;
        return xVal.CompareTo(yVal);
    }

    // fallback for everything else
    return x.CompareTo(y);
}

 

Let me know if you have any questions about how this works or see any flaws in my logic!