通过包含原始子串的另一个列表对字符串列表进行排序

时间:2017-07-13 19:18:36

标签: java list sorting

关于这个话题,我已经尝试了所有其他问题和答案,但我还没有设法让它发挥作用。

我有一个特别排序的字符串列表,例如:["serviceT", "servicC", "serviceA", ... "serviceZ"]

我有另一个同名jar文件的完整路径列表: ["C:\Users\USER\projects .... \serviceB-1.0-SNAPSHOT.jar" ...]。此列表完全无序。此列表使用以下内容生成:

servicesPaths = Files.walk(Paths.get(parentFolder))
    .map(Path::toString)
    .filter(path -> {
        boolean flag = false;
        for (String service : services)
            if (path.endsWith(version + ".jar") && path.contains(service)) flag = true;
            return flag;
    })
    .collect(Collectors.toList());

基本上我只是给它一个父文件夹,它返回包含service的所有路径的列表。两个列表的大小相同。我的意思是,每个service只有一个path

我需要订购servicePath列表,以便它与services有序列表的顺序相同。

我已经尝试过使用我能想到的各种排序/比较方法,并且只能使用非常粗暴的for循环来实现它:

List<String> temp = new ArrayList<>();
for (String service : services)
    for (String path : servicesPaths)
        if (path.indexOf(service) > 0)
            temp.add(path);

还有其他明智的方法可以对servicePaths列表进行排序吗?

5 个答案:

答案 0 :(得分:1)

第一个优化:由于两个列表的大小相同,因此添加后可以删除路径。这减少了外循环每次运行的内循环次数。

但是我会做什么:改变生成该路径列表的方式。你看:首先你已经有了另一个N * N.然后另一个N * N后来一个?!

相反:

  • 将您的服务放入Map<String, Integer>:key是字符串,重视服务列表中的索引
  • 为路径创建列表 - 其中包含服务插槽!
  • 然后,当您处理文件路径时,只需检查每个Map键是否“匹配” - 并且匹配...您只需查看该地图,您就知道该路径应该具有的位置。因此,您只需将其插入您在步骤2中准备的列表中即可!

应该足以让你前进 - 我想你将不得不仔细研究诸如“列表大小真正相同”之类的约束等等(如果你的路径少于服务,那么中间列表可能包含一些空槽然后你必须删除)。

答案 1 :(得分:1)

一个非常直接的解决方案,但我认为这是合适的:

List<String> services = Arrays.asList("serviceA", "serviceC", "serviceB");
List<String> servicesPaths = Arrays.asList("serviceA-bla-bla", "serviceB-bla-bla", "serviceC-bla-bla");
List<String> sortedServices = servicesPaths.stream()
            .sorted((a, b) -> Integer.compare(
                    services.indexOf(a.substring(0, a.indexOf("-"))), 
                    services.indexOf(b.substring(0, b.indexOf("-")))))
            .collect(Collectors.toList());

子字符串部分只是从路径中提取服务名称。如果你有任何其他方法,只需用其他方式替换它。

另外,我会通过将比较函数存储在变量中来改进此片段:

Function<String, Integer> indexInServices = path -> services.indexOf(path.substring(0, path.indexOf("-")));
List<String> orderedServices = servicesPaths.stream()
      .sorted(Comparator.comparing(indexInServices))
      .collect(Collectors.toList());

答案 2 :(得分:1)

按字符串“servicesPaths

后面的子字符串排序Service

m 大小为servicesPath n 为已排序字符串的大小。

然后使用伪代码

for each string in servicesPath search SortedStrings by binary search

此解决方案是时间 O(m log(n))* 因为二进制搜索是命令 O(log n)

你的暴力解决方案是时间* O(m * n)*

排序路径的大小是否应小于排序字符串的大小 创建一个记录数组。 (注意,这不是海报的情况。)

class Pair {
     String str;
     int pos;
   }
   Pair []Pairs;
   Pairs = new Pair[sorted strings.length];

对于排序字符串中的每个项目,将字符串复制到Pair[i]s.str和 其序号位置为Pairs[i].pos

然后,使用简单的比较器

Pairs排序str

然后,对于servicesPaths中的每个项目,您将获取字符串并执行二进制文件 在Pairs中。当您找到匹配的那个时,请调用其位置pos。 将该servicesPaths项复制到path[pos]

对于CS2(数据结构)类,这是一个很好的练习。

答案 3 :(得分:0)

您可能意识到需要根据require('config.php');索引进行排序。这是另一种做你需要的方法:

services

答案 4 :(得分:-1)

列表中您称为“已排序”的每个项目(但实际上只是根据某些不透明的标准进行排序)在列表中有一个位置或索引。

这个位置/索引是用于排序其他列表的关键。

对于要排序的列表中的每个元素,在“ordered”列表中查找它,并将找到的元素的索引作为排序键应用。