Как вывести необычное значение между двумя массивами? - PullRequest
0 голосов
/ 25 апреля 2020

Я хочу сравнить значение, сохраненное в имени файла [i] и имени файла [j], и распечатать значение в имени файла [i], имя которого не совпадает с именем файла [j]. Я знаю, что это можно сделать, используя set_difference и решение для сортировки, но я точно не знаю, как написать код sort и set_differences. Здесь я предоставляю свой оригинальный код, чтобы вы могли проверить его и лучше понять, что я пытаюсь сделать.

мой полный код:

#include <string>
#include <iostream>
#include <ctime> //important when to make random filename- srand(time(0))
#include <opencv2\opencv.hpp> //important when using opencv
#include <vector>   //when using vector function

using namespace std;
using namespace cv; //important when using opencv

int main(int argc, char* argv[]) {

vector<String> filenames;
int a, i;
srand(time(0)); //seed random filenames - for random filename


// Get all jpg in the folder

cv::glob("C:\\Users\\x\\Documents\\Aggressive\\abc", filenames);

for (size_t i = 0; i < filenames.size(); i++)
{
    Mat im = imread(filenames[i]); //read the filename location


   std::cout << "\n";

    std::size_t found = filenames[i].find_last_of("//\\");
    //std:cout << " file: " << filenames[j].substr(found + 1) << '\n'; //display filename and its format (.jpg)

    std::string::size_type const p(filenames[i].substr(found + 1).find_last_of('.')); //eg: 2.jpg then it will find the last '.'
    std::string file_without_extension = filenames[i].substr(found + 1).substr(0, p); //eg: 2
    std::cout << " file : " << filenames[i].substr(found + 1).substr(0, p); //display filename without .jpg



}

cout << "\n";
cout << "There's " << filenames.size() << " files in the current directory.\n" << endl; // total file in the specific directory

cout << "Enter array size: \n";
cin >> a;

for (int j = 0; j < filenames.size(); j++) {
    //generate random filename
    int index = rand() % filenames.size(); //random based on total of the file in the directory
    //cout << filenames[index] << endl; //display the random number but might be redundant

    //swap filenames[j] with filenames[index]
    string temp = filenames[j];
    filenames[j] = filenames[index];
    filenames[index] = temp;
}

for (int j = 0; j < a; j++) {

    //cout << "Random image selected:" << filenames[j] << endl; //basically to avoid the redundant random filename

    Mat im = imread(filenames[j]); //read filename location

    std::size_t found = filenames[j].find_last_of("//\\");
    //std:cout << " file: " << filenames[j].substr(found + 1) << '\n'; //display filename and its format (.jpg)

    std::string::size_type const p(filenames[j].substr(found + 1).find_last_of('.')); //eg: 2.jpg then it will find the last '.' 
    std::string file_without_extension = filenames[j].substr(found + 1).substr(0, p); //eg: 2
    std::cout << " file: " << filenames[j].substr(found + 1).substr(0, p); //display filename without .jpg

    string written_directory = "C:/Users/x/Documents/folder/" + filenames[j].substr(found + 1).substr(0, p) + ".jpg"; // write filename based on its original filename.
    imwrite(written_directory, im);

}


return 0;
}

1 Ответ

1 голос
/ 26 апреля 2020

На мой взгляд, это прекрасный пример проблемы XY . Из твоего вопроса, из твоего кода и даже из комментариев люди не совсем понимают, что ты хочешь делать. Имея это в виду, чего вы хотите достичь?

Неясно, хотите ли вы скопировать определенное количество случайно выбранных файлов JPEG из одного каталога в другой. И что вы хотите показать имена файлов файлов, которые не будут скопированы.

Позвольте мне привести несколько примеров, в чем причина всей этой путаницы.

Первое и самое важное, Вы не показываете полный код. Определения и типы переменных и функции не соответствуют. Это также не Минимум, воспроизводимый пример . И описание в вашем вопросе трудно понять.

У меня есть два набора массивов

У вас есть "два набора массивов"? Вы имеете в виду, у вас есть 2 [std::set][3] из [std::array][3]. Или, может быть, у вас просто 2 [std::vector][3] из std::string. Из того, что мы можем видеть в коде, мы могли бы предположить std::vector<std::string>>, но мы не знаем, потому что вы не показывали определение «имен файлов».

Тогда вы говорите о «2» что-то. Но мы видим только одно"имен файлов". Итак, 2 или 1?

в комментарии, который вы пишете

в массиве 2 У меня было случайное имя файла в зависимости от размера массива, который пользователь ввел

Я предполагаю, что вы не хотите иметь случайное имя файла, но хотите выбрать имена файлов со случайным индексом из первого вектора и поместить его во второй вектор? Но мы можем видеть только один вектор «имен файлов», в котором вы выполняете некоторую случайную замену.

Тогда вы написали

На самом деле imread читает весь файл в папке каталога.

Эта функция очень важна, что она делает? А что вы подразумеваете под "читать файл"? Вы имеете в виду «имя файла», так имя файла? Или содержимое файла? И что означает "папка каталога"? Все имена файлов в одной папке? Или подпапка записи каталога?

Так что теперь моя цель - распечатать все файлы, которые не имеют одинакового имени файла в массиве 2

Опять же, делаем ли мы действительно есть 2 массива (вектор)? они разные?

А потом, куда вы копируете файлы?


Итак, вы видите, это очень трудно понять. Даже если люди хотят помочь вам, они не могут, потому что они не понимают вас. Лучше показать ссылку на оригинальную домашнюю работу. Тогда люди могут помочь вам. Пользователи здесь на Stack Overflow хотят помочь. Но, пожалуйста, позвольте им сделать это.

Здесь я приведу абстрактный пример для задачи случайного выбора и задачи set_difference:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <random>

int main() {
    // Define 2 Vectors for filenames

    // This vector is an example for files that could be in a specified directory
    std::vector<std::string> fileNamesInDirectory{"8.jpg","5.jpg", "6.jpg", "9.jpg", "1.jpg", "4.jpg", "2.jpg", "3.jpg", };

    // Print the filenames as information for the user
    for (size_t i = 0U; i < fileNamesInDirectory.size(); ++i) {
        std::cout << fileNamesInDirectory[i] << "\n";
    }

    // Next: Select randomly a given number of filenames from the above vector

    // So, first get the number of selections. Inform the user
    std::cout << "\nEnter a number of filenames that should be copied randomly. Range: 1-"<< fileNamesInDirectory.size()-1 << "\t";
    size_t numberOfSelectedFileNames{};
    std::cin >> numberOfSelectedFileNames;

    // Check for valid range
    if (numberOfSelectedFileNames == 0 || numberOfSelectedFileNames >= fileNamesInDirectory.size()) {
        std::cerr << "\n*** Error. Wrong input '" << numberOfSelectedFileNames << "'\n";
    }
    else {
        // Copy all data from fileNamesInDirectory
        std::vector<std::string> selection{ fileNamesInDirectory };

        // Shuffle the data randomly: Please see here: https://en.cppreference.com/w/cpp/algorithm/random_shuffle
        std::random_device rd;
        std::mt19937 g(rd());
        std::shuffle(selection.begin(), selection.end(), g);

        // Resize to the number, given by the user
        selection.resize(numberOfSelectedFileNames);

        // Now we have a random list of filenames
        // Show, what we have so far. Now, because we are learning, we will use the range based for
        std::cout << "\n\nOriginal file names:\n";
        for (const std::string& s : fileNamesInDirectory) std::cout << s << "\n";
        std::cout << "\n\nRandomly selected file names:\n";
        for (const std::string& s : selection) std::cout << s << "\n";

        // Sort both vectors
        std::sort(fileNamesInDirectory.begin(), fileNamesInDirectory.end());
        std::sort(selection.begin(), selection.end());

        // Show again to the user:3

        std::cout << "\n\nOriginal file names sorted:\n";
        for (const std::string& s : fileNamesInDirectory) std::cout << s << "\n";
        std::cout << "\n\nRandomly selected file names sorted:\n";
        for (const std::string& s : selection) std::cout << s << "\n";

        // Now, find out the difference of both vectors, meaning, what will not be selected and later copied
        std::vector<std::string> difference{};

        // Calculate the difference with a std::algorithm: https://en.cppreference.com/w/cpp/algorithm/set_difference
        std::set_difference(fileNamesInDirectory.begin(), fileNamesInDirectory.end(), selection.begin(), selection.end(), std::back_inserter(difference));

        std::cout << "\n\nThe following file names have not been selected:\n";
        for (const std::string& s : difference) std::cout << s << "\n";

    }
    return 0;
}

Если вы более продвинуты, вы можете и будете использовать функции из файловой системы C ++ библиотека . Это облегчит жизнь. , .

...