简体   繁体   English

如何对服装尺码列表进行排序(例如 4XL、S、2XL)?

[英]How can I sort a list of clothing sizes (e.g. 4XL, S, 2XL)?

I need your help follow query.我需要您的帮助来跟踪查询。 Given the following List:鉴于以下列表:

["2XL", "3XL", "4XL", "5XL", "6XL", "L", "M", "S", "XL"]

How do I sort it so that it is in this order?我如何对其进行排序以使其按此顺序排列?

["S", "M", "L", "XL", "2XL", "3XL", "4XL", "5XL", "6XL"] [“S”、“M”、“L”、“XL”、“2XL”、“3XL”、“4XL”、“5XL”、“6XL”]

Note that every size is not always present.请注意,并非所有尺寸都存在。

Build a comparator which does a lookup on your desired order:构建一个比较器,它会根据您想要的顺序进行查找:

Comparator<String> sizeOrder = Comparator.comparingInt(desiredOrder::indexOf);

where哪里

desiredOrder = Arrays.asList("S", "M", "L", "XL", "2XL", "3XL", "4XL", "5XL", "6XL");

Then:然后:

yourList.sort(sizeOrder);

If you want, you can build a Map<String, Integer> for the lookup:如果需要,您可以为查找构建一个Map<String, Integer>

Map<String, Integer> lookup =
    IntStream.range(0, desiredOrder.length())
        .boxed()
        .collect(Collectors.toMap(desiredOrder::get, i -> i));

And then do:然后做:

Comparator<String> sizeOrder = Comparator.comparing(lookup::get);

I'm not convinced that this will be any more performant than using List.indexOf , because the desiredOrder list is so small.我不相信这会比使用List.indexOfList.indexOf ,因为desiredOrder列表太小了。

As with everything performance-related: use the one which you find most readable;与所有与性能相关的内容一样:使用您认为最易读的; profile if you think this is a performance bottleneck, and only then try alternatives. profile 如果您认为这是一个性能瓶颈,那么只有尝试替代方案。

A general approach would focus on the pattern behind the size strings rather than just accommodating the sample input.一般方法将关注大小字符串背后的模式,而不仅仅是容纳样本输入。 You have a fundamental direction denoted by S , M , or L and optional modifiers before it (unless M ) altering the magnitude.您有一个由SML表示的基本方向和可选的修饰符(除非M )改变幅度。

static Pattern SIZE_PATTERN=Pattern.compile("((\\d+)?X)?[LS]|M", Pattern.CASE_INSENSITIVE);
static int numerical(String size) {
    Matcher m = SIZE_PATTERN.matcher(size);
    if(!m.matches()) throw new IllegalArgumentException(size);
    char c = size.charAt(m.end()-1);
    int n = c == 'S'? -1: c == 'L'? 1: 0;
    if(m.start(1)>=0) n *= 2;
    if(m.start(2)>=0) n *= Integer.parseInt(m.group(2));
    return n;
}

Then, you can sort a list of sizes like然后,您可以对尺寸列表进行排序,例如

List<String> sizes = Arrays.asList("2XL", "5XL", "M", "S", "6XL", "XS", "3XS", "L", "XL");
sizes.sort(Comparator.comparing(Q48298432::numerical));
System.out.print(sizes.toString());

where Q48298432 should be replaced with the name of the class containing the numerical method.其中Q48298432应替换为包含numerical方法的类的名称。

An alternative using the probably more efficient and certainly clearer enum route.使用可能更有效且当然更清晰的enum路线的替代方法。

// Sizes in sort order.
enum Size {
    SMALL("S"),
    MEDIUM("M"),
    LARGE("L"),
    EXTRA_LARGE("XL"),
    EXTRA2_LARGE("2XL"),
    EXTRA3_LARGE("3XL"),
    EXTRA4_LARGE("4XL"),
    EXTRA5_LARGE("5XL"),
    EXTRA6_LARGE("6XL");
    private final String indicator;

    Size(String indicator) {
        this.indicator = indicator;
    }

    static final Map<String,Size> lookup = Arrays.asList(values()).stream()
            .collect(Collectors.toMap(
                    // Key is the indicator.
                    s -> s.indicator,
                    // Value is the size.
                    s-> s));

    public static Size lookup(String s) {
        return lookup.get(s.toUpperCase());
    }

    // Could be improved to handle failed lookups. 
    public static final Comparator<String> sizeOrder = (o1, o2) -> lookup(o1).ordinal() - lookup(o2).ordinal();
}

public void test(String[] args) {
    List<String> test = Arrays.asList("S","6XL", "L");
    Collections.sort(test, Size.sizeOrder);
    System.out.println(test);
}

Another way could be this:另一种方式可能是这样的:

List<String> desiredOrder = Arrays.asList("S", "M", "L", "XL", "2XL", "3XL", "4XL", "5XL", "6XL");
 String [] array = new String[desiredOrder.size()];
   list.forEach(s->{
       if (desiredOrder.indexOf(s) != -1)
             array[desiredOrder.indexOf(s)] = s;
   });

List<String> set= Stream.of(array).filter(Objects::nonNull).collect(Collectors.toList());

Or或者

Set<Integer> integers = new HashSet<>();
    list.forEach(s -> {
        if (desiredOrder.indexOf(s) != -1) {
            integers.add(desiredOrder.indexOf(s));
        }
    });

    List<String> sortedItems = integers.stream()
                                       .sorted()
                                       .map(i->desiredOrder.get(i))
                                       .collect(Collectors.toList());

This is a basic algorithm to complete the size sorting.这是完成大小排序的基本算法。 the basic idea of this algorithm is break each parts ( number , modifier , unit ) of size into the corresponding regions ( [0, 1000) , [1000, 1000_000) , [1000_000, reset] ), and then use dir to decide the direction of the modifier .该算法的基本思想是将大小的每个部分( numbermodifierunit )分解为相应的区域( [0, 1000)[1000, 1000_000)[1000_000, reset] ),然后使用dir来决定modifier方向。 for example:例如:

class Size {
  public static int sizeToInt(String size) {
    int n = size.length(), unit = size.charAt(n - 1), dir = unit == 'S' ? 1 : -1;
    //use a separate method to parse the number & extra modifier if needed
    int i = 0;
    int number = n > 1&&Character.isDigit(size.charAt(i)) ? size.charAt(i++) : '1';
    int modifier = i + 1 < n ? size.charAt(i) : 0;
        return -1 * (unit * 1000_000 + dir * (modifier * 1000 + number));
  }
}

The solution above is just for the simple case as yours, for the complex case you need to parse number & modifier and decide how to partition the region s.上面的解决方案仅适用于您的简单情况,对于复杂情况,您需要解析number & modifier并决定如何对region进行分区。 Then you can sort sizes by Comparator as following code:然后您可以按以下代码按Comparator对大小进行排序:

Comparator<String> sizeComparator = Comparator.comparingInt(Size::sizeToInt);

List<String> sizes = Arrays.asList(
    "3XL", "2XL", "XL",
    "5L", "2L", "L",
    "5M", "2M", "M",
    "S", "2S", "3S",
    "XS", "2XS", "3XS"
);


sizes.sort(sizeComparator);

System.out.println(sizes);
//                  ^--- [
//                         "3XS", "2XS", "XS",
//                         "3S", "2S", "S",
//                         "M", "2M", "5M",
//                         "L", "2L", "5L",
//                         "XL", "2XL", "3XL"
//                       ]

Create an Enum class with all the possible sizes and add to it the getEnum method to support the sizes that start by number:创建一个包含所有可能大小的 Enum 类,并向其中添加getEnum方法以支持以数字开头的大小:

public enum SizeEnum
{
    S("S"), M("M"), L("L"), XL("XL"), TWO_XL("2XL"), THREE_XL("3XL"), FOUR_XL("4XL"), FIVE_XL("5XL"), SIX_XL("6XL");

    private String value;

    SizeEnum(String value){
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public static SizeEnum getEnum(String value) {
        return Arrays.stream(values())
                .filter(v -> v.getValue().equalsIgnoreCase(value))
                .findAny()
                .orElseThrow(() -> new IllegalArgumentException());
    }
}

Use the SizeEnum class in the comparator:在比较器中使用SizeEnum类:

List<String> sizes = Arrays.asList("2XL", "3XL", "4XL", "5XL", "6XL", "L", "M", "S", "XL");
sizes.sort(Comparator.comparing(v -> SizeEnum.getEnum(v.toUpperCase())));
sizes.stream().forEach(l -> System.out.println(l));
public static void SortSizes(String [] sizes, String [] sortedRadixArr) throws Exception{
    
    //creating an int array with same length as sortedRadixArr
    //Here each index of intRadix array is mapped to the index of sortedRadixArr
    //Eg:           intRadix = [0,0,0,0,0]  ----> ["S","M","L","XL","2XL"]  

    int [] intRadix = new int[sortedRadixArr.length];
    
    for(int i = 0; i < sizes.length; i++){
        boolean  matchFlag = false;
        for(int j=0; j< sortedRadixArr.length; j++){
            if(sizes[i] == sortedRadixArr[j]){
                //Whenever the String is matched with the String of sortedRadixArr array, 
                //increment the value of intRadix array at the equivalent index of sortedRadixArr.
                //This helps us to count number same strings(sizes). like two or more "S". 
                //We can't do that with sortedRadixArr as it is a String array.
                intRadix[j]++;
                matchFlag = true;
                break;
            }
        }
        if(!matchFlag){
            throw new Exception("Invalid size found!");
        }
    }
    int count = 0;
    for(int k = 0; k < intRadix.length; k++){
        //Loop thru intRadix array. It contains count of respective sizes(Strings) at each index. 
        //We will re-write sizes array in sorted order with help of intRadix as below.
        while(intRadix[k] > 0){
            sizes[count++] = sortedRadixArr[k];
            intRadix[k]--;
        }
    }
}

} }

Here, sortedRadixArr is the radix array ie values with all possible values:这里, sortedRadixArr是基数数组,即具有所有可能值的值:

["S", "M", "L", "XL", "2XL", "3XL", "4XL", "5XL", "6XL"]

sizes is the array that you wanna sort: sizes是您要排序的数组:

["2XL", "3XL", "4XL", "5XL", "6XL", "L", "M", "S", "XL"]

It accepts duplicate values.它接受重复值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 基于值顺序的Java排序对象列表(例如d,s,a,q,c) - Java Sort object list based on value order (e.g. d, s, a, q, c) 在 Pixel 4XL 上检测生物识别失败并显示 BIOMETRIC_ERROR_HW_UNAVAILABLE - Detecting biometrics on Pixel 4XL fails with BIOMETRIC_ERROR_HW_UNAVAILABLE 如何以编程方式动态创建所有Android ui组件的列表?例如TextView,ImageView等 - How can I dynamically create a list of all Android ui components programmatically? e.g. TextView, ImageView etc 如何在组级别实施ACL? 例如,只有学校A的老师可以更新学校A的日历 - How to implement ACL at a group level? E.g. only teachers in school A can update school A's calendar 如何使用HtmlUnit检查我是否登录了网站(例如LinkedIn)? - How can I check if I logged in a website (e.g. LinkedIn) using HtmlUnit? 如何使用eclipse中编写的Java代码在远程桌面中导航(例如,打开Mozilla)? - How can i navigate (e.g. open Mozilla) in a Remote Desktop by using java code written in eclipse? 我如何读取在KieSession外部插入的事实(例如规则结果)? - How can I read facts outside of the KieSession that were inserted inside of the KieSession­ (e.g. rules results)? 在 Java 正则表达式中,如何获取字符类(例如 [az])以匹配 - 减号? - In a java regex, how can I get a character class e.g. [a-z] to match a - minus sign? 如何检查数组的所有元素是否不等于某个值? (例如,不是空的) - How can I check if all elements of array doesn't equal to some value? (e.g. not empty) 如何从另一个类访问对象(例如ArrayList)? - How can I access an object (e.g. ArrayList) from another class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM