查找数组是否为另一个数组的子集

时间:2019-04-02 10:11:31

标签: java arrays subset

仅当参数对象是调用对象的子集时,此函数才应返回true,但始终返回true。如何解决?

    public boolean contains(FileCollection other) {
        int i = 0;
        int j = 0;
        for (i = 0; i<other.files.length; i++) {
            for (j = 0; j<this.files.length; j++) {
                if ((other.files[i]).equals((this.files[j]))) //this refers to the equals method defined in File class
                    break;
            }
            if (j==this.files.length) 
                return false;
        }
        return true;//this method is in FileCollection class
    }

5 个答案:

答案 0 :(得分:3)

(因为您没有明确表示数组元素的数据类型是什么,所以我假设它是File,从注释中推断出来。)

如果您不介意在数据结构之间进行转换,则将数组(临时)转换为Collections是最简单的方法。例如,转换为List

/* @param other
 * @return true if the calling object contains
 * all files in the parameter object, false otherwise
 */
public boolean contains(FileCollection other) {
    List<File> myList = Arrays.asList(this.files);
    List<File> otherList = Arrays.asList(other.files);
    return myList.containsAll(otherList);
}

基于您对允许重复项时被视为“包含”的澄清,我想您需要计算每个元素的存在数量。方法如下:

基于@Eritrean的答案,您可以获取计数并将其存储到地图。我也进行了修改以检查计数:

public boolean contains(FileCollection other) {
    Map<File,Integer> otherFrequency = Arrays.stream(other.files)
            .collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));

    Map<File,Integer> thisFrequency  = Arrays.stream(this.files) 
            .collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));

    if (thisFrequency.entrySet().containsAll(otherFrequency).entrySet()) {
        for (File entry : otherFrequency.entrySet()) {
            if (thisFrequency.get(entry) < otherFrequency.get(entry))
                return false;
        }
        return true;
    }
    return false;
}

答案 1 :(得分:2)

要让other.files包含this.files,每个this.file必须在other.files中。

    for (int j = 0; j < this.files.length; j++) {
        boolean found = false;
        for (int i = 0; i < other.files.length; i++) {
            if (other.files[i].equals(this.files[j])) {
                found = true;
                break;
            }
        }
        if (!found) { 
            return false;
        }
    }
    return true;

您可能不知道files的类别,

    for (String file : this.files) {
        boolean found = false;
        for (String otherFile : other.files) {
            if (otherFile.equals(file)) {
                found = true;
                break;
            }
        }
        if (!found) { 
            return false;
        }
    }
    return true;

甚至

    for (String file : this.files) {
        boolean found = other.files.indexOf(file) != -1;
        if (!found) { 
            return false;
        }
    }
    return true;

有更好的数据结构可以加快处理速度,并为contains之类的事情提供了预定义的方法。


具有重复项

    Comparator<File> comparator = new Comparator<File>() {
        @Override
        public int compare(File lhs, File rhs) {
            int cmp = lhs.getBase().compareIgnoreCase(rhs.getBase());
            if (cmp == 0) {
               cmp = lhs.getExtension().compareIgnoreCase(rhs.getExtension());
            }
            if (cmp == 0) {
               cmp = Long.compare(lhs.getSize(), rhs.getSize());
            }
            return cmp;
        }
    };

    Arrays.sort(this.files, comparator);
    Arrays.sort(other.files, comparator);
    int otherI = 0;
    for (File file : this.files.length) {
        boolean found = false;
        while (otherI < other.files.length) {
            int comparison = comparator.compare(other.files[otherI], file);
            ++otherI;
            if (comparison >= 0) {
                found = comparison == 0;
                break;
            }
        }
        if (!found) { 
            return false;
        }
    }
    return true;

通过对两个数组进行排序,您可以在两个数组中的位置同步比较。上面处理重复项。

答案 2 :(得分:1)

除了@renyuneyun建议将数组转换为列表之外,您还可以使用String contains方法

public boolean contains(FileCollection other) {
String myList = Arrays.toString(this.files);
String otherList = Arrays.toString(other.files);
return myList.contains(otherList);
}

当然,从复杂性的角度来看,这两个建议都不是最佳解决方案,但是肯定是最短的:)

答案 3 :(得分:1)

如何使用以File为键,频率为值的地图:

public boolean contains(FileCollection other) {
    Map<File,Integer> otherFrequency = Arrays.stream(other.files)
            .collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));

    Map<File,Integer> thisFrequency  = Arrays.stream(this.files) 
            .collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));

    return thisFrequency.entrySet().containsAll(otherFrequency.entrySet());
}

答案 4 :(得分:0)

仅此答案对我有用:(为“比较器”部分致谢@Joop Eggen)

public boolean contains(FileCollection other) {
    Comparator<File> comparator = new Comparator<File>() {
        @Override
        public int compare(File lhs, File rhs) {
            int cmp = lhs.getBase().compareToIgnoreCase(rhs.getBase());
            if (cmp == 0) {
               cmp = lhs.getExtension().compareToIgnoreCase(rhs.getExtension());
            }
            if (cmp == 0) {
               cmp = Long.compare(lhs.getSize(), rhs.getSize());
            }
            if (cmp == 0) {
               cmp = Long.compare(lhs.getPermissions(), rhs.getPermissions());
            }
            return cmp;
        }
    };
    Arrays.sort(this.files, comparator);
    Arrays.sort(other.files, comparator); //THIS AND THE COMPARATOR SORT THE ARRAYS BASED ON ALL FILE ATTRIBUTES    
    int i = 0;
    int j = 0;
    if (this.files.length<other.files.length)
        return false;
    while (i<other.files.length && j<this.files.length) {
        if (!(this.files[j].equals(other.files[i])))
            j++;
        else {
            j++;
            i++;
        }
    }
    if (i<other.files.length)
        return false;
    else
        return true; 
}