Найти массив, если он является подмножеством другого массива - PullRequest
2 голосов
/ 02 апреля 2019

Эта функция должна возвращать истину, только если объект параметра является подмножеством вызывающего объекта, но всегда возвращает истину.Как это исправить?

    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 ]

3 голосов
/ 02 апреля 2019

(Поскольку вы не указали явно тип данных элементов массива, я предполагаю, что это File, выведенное из комментариев.)

Если вы не возражаете против преобразования между структурами данных, возможно, преобразование ваших массивов (временно) в коллекции является наиболее простым способом. Например, преобразование в 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;
}
2 голосов
/ 02 апреля 2019

Для 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;

Сортировав оба массива, вы можете синхронизировать сравнение в местоположениях обоих массивов.Вышеуказанные ручки дубликатов.

1 голос
/ 02 апреля 2019

Как насчет использования карты с Файлом в качестве ключа и частотой в качестве значения:

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());
}
1 голос
/ 02 апреля 2019

Помимо предложения @renyuneyun для преобразования ваших массивов в списки, вы также можете использовать метод String contains

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

Конечно, оба эти предложения не являются оптимальными решениями с точки зрения сложности, но, безусловно, являются самыми короткими:)

0 голосов
/ 14 мая 2019

У меня работает только этот ответ: (Благодарю @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; 
}
...