Refer to the Java implementation of commodity specification selector algorithm based on adjacency matrix on the Internet, which is used in android APP, does not include adapter part, just the part of the matrix tool class

The principles and renderings are referenced in this blog post

Data structure definition


// 1. Certain specifications
public static class Spec {
    public String type;
    public List<String> values;
}
Copy the code

For example, the new Spec (” color “, [” red “, “blue”])

// 2. A specification value
public static class OneSpec {
    public String type;
    public String value;
    public int idx = -1;
}
Copy the code

For example the new OneSpec (” color “, “red”)

// 3. Sku specifications
public static class ItemSpecs {
    public String sku;
    public List<OneSpec> specs = new ArrayList<>();
}
Copy the code

Such as new ItemSpecs (skuCode, [” red “, “128 g”])

// 4. Specification selector utility class
public class ItemSpecsAdjoinMatrix {

    private List<OneSpec> flattenSpecs = new ArrayList<>(); // All dimensions (the edges that make up the adjacency matrix)
    private int[][] matrix; // Adjacency matrix
    private Map<String, String> skuMap = new HashMap<>(); // Map skUs based on a combination of specification values
    private OneSpec[] selectedSpecArray; // Save the currently selected values for each type of specification (at most one for each type)
    
}
Copy the code

Construct the adjacency matrix

The adjacency matrix is constructed from the list of optional SKUs and the list of total specifications

I feel so clever when I set the row number and set the specification combination SKU mapping table

public ItemSpecsAdjoinMatrix(List<ItemSpecs> itemSpecs, List<Spec> specs) {
    // 1. Initialize to none
    selectedSpecArray = new OneSpec[specs.size()];
    for (int i = 0; i < specs.size(); i++) {
        selectedSpecArray[i] = new OneSpec(specs.get(i).type, "");
    }
    // 2. "slap" the specification value to save, and set the line number in the matrix
    int idx = 0;
    for (Spec spec : specs) {
        for (String s : spec.values) {
            flattenSpecs.add(newOneSpec(spec.type, s, idx)); idx++; }}// 3. Label commodity specification values with row numbers to facilitate the connectivity of matrix nodes through coordinates
    for (ItemSpecs item : itemSpecs) {
        for(OneSpec oneSpec : item.specs) { setOneSpecIdx(oneSpec); }}// 4. Save the mapping table between specification combination strings and SKU
    String[] skuKey = new String[selectedSpecArray.length];
    for (ItemSpecs item : itemSpecs) {
        for (OneSpec oneSpec : item.specs) {
            for (int i = 0; i < specs.size(); i++) {
                if (TextUtils.equals(specs.get(i).type, oneSpec.type)) {
                    skuKey[i] = oneSpec.value;
                }
            }
        }
        StringBuilder str = new StringBuilder();
        for (String key : skuKey) str.append(key);
        skuMap.put(str.toString(), item.sku);
    }
    // 5. Initialize matrix, default same type of points connected, all other points are disconnected
    int n = flattenSpecs.size();
    matrix = new int[n][n];
    for (int r = 0; r < n; r++) {
        for (int c = 0; c < n; c++) {
            matrix[r][c] = 0;
            if (TextUtils.equals(flattenSpecs.get(r).type, flattenSpecs.get(c).type)) matrix[r][c] = 1; }}// 6. Mark the connection point corresponding to the SKU
    for (ItemSpecs item : itemSpecs) {
        for (OneSpec rowSpec : item.specs) {
            int r = rowSpec.idx;
            for (OneSpec colSpec : item.specs) {
                int c = colSpec.idx;
                matrix[r][c] = 1; }}}}Copy the code

Selector click event handling

// 1. Update the selected array
public String refreshSelectedSpec(OneSpec oneSpec) {
    setOneSpecIdx(oneSpec);
    for (OneSpec spec : selectedSpecArray) {
        if (TextUtils.equals(spec.type, oneSpec.type)) {
            if (TextUtils.equals(spec.value, oneSpec.value)) {
            // Deselect
                spec.value = "";
                spec.idx = -1;
            } else {
            // Update the selected specifications
                spec.value = oneSpec.value;
                spec.idx = oneSpec.idx;
            }
            break;
        }
    }
    String str = "";
    for (OneSpec spec : selectedSpecArray) {
        str += spec.value;
    }
    return skuMap.get(str); // Returns the selected skucode
}
Copy the code

// 2. Obtain the enabled status of each specification value according to the SKU algorithm.
public int[] getEnabledSpecs() {
    int n = flattenSpecs.size();
    int[] tmp = new int[n];
    for (int i = 0; i < n; i++) tmp[i] = 1;
    for (OneSpec spec : selectedSpecArray) {
        int c = spec.idx;
        if (c == -1) continue;
        for (int r = 0; r < n; r++) {
            if (matrix[r][c] == 0) {
                tmp[r] = 0; }}}return tmp;
}
Copy the code

The control color can then be displayed based on the enabled and Selected states