Разбор файла CSV без использования вектора в C ++ - PullRequest
0 голосов
/ 07 декабря 2018

Я работаю над проектом C ++ в Visual Studio.У меня есть CSV-файл, который выглядит следующим образом:

"0","12312415"," my whole body is tired"
"0","12365448","I just want to rest my ears because of I do not see"
"0",123156984","I want to go to cinema with my girls friend. I am so tired"

Итак, я хочу проанализировать эти данные без использования вектора и положить в массив.Затем я найду общие слова в последнем элементе массива.Мой ожидаемый результат выглядит следующим образом:

<I> <four times count
<my> <three times count>
<to> <three times count>

Есть ли способ сделать это?Я использую этот код для сортировки, но я не знаю, как преобразовать мой код, для чтения и помещения данных в массив.

void heapify(int arr[], int n, int i)
{
    int largest = i; // Initialize largest as root
    int l = 2 * i + 1; // left = 2*i + 1
    int r = 2 * i + 2; // right = 2*i + 2

    // If left child is larger than root
    if (l < n && arr[l] > arr[largest])
        largest = l;

    // If right child is larger than largest so far
    if (r < n && arr[r] > arr[largest])
        largest = r;

    //If largest is not root
    if (largest != i)
    {
        swap(arr[i], arr[largest]);

        //Recursively heapfy the affected sub-tree
        heapify(arr, n, largest);
    }
}

// main function to do heap sort

void heapSort(int arr[], int n)
{

    // Build heap (rearrange array)
    for (int i = n / 2 - 1; i >= 0; i--)
        heapify(arr, n, i);

    //One by one extract an element from heap
    for (int i = n - 1; i >= 0; i--)
    {
        // Move current root to end
        swap(arr[0], arr[i]);

        // Call max heapify on the reduced heap
        heapify(arr, i, 0);
    }
}

// A utility function to print array of size n

void printArray(int arr[], int n)
{
    for (int i = 0; i < n; ++i)
        cout << arr[i] << " ";
    cout << "\n";
}
int main()
{
    clock_t begin = clock();
    int arr[] = { 12,11,13,5,6,7,62,25,27 };
    int n = sizeof(arr) / sizeof(arr[0]);

    heapSort(arr, n);
    cout << "Sorted array is \n";

    printArray(arr, n);

    clock_t end = clock();
    float elapsed_secs = float(end - begin) / CLOCKS_PER_SEC;
    cout << "Time elapsed Time: " << elapsed_secs << " seconds" << endl;

    system("PAUSE");
    return 0;
}

1 Ответ

0 голосов
/ 08 декабря 2018

Поскольку вы не хотите использовать std::vector, что является рекомендуемым способом, вы должны использовать 2D-массив для чтения файла CSV.Первое измерение массива - это количество строк, а второе измерение - количество полей.В вашем случае оба измерения равны 3. Проверьте Считайте CSV-файл, используя для этого 2d массив .


Как только вы подготовите 2D-массив, вам нужно посчитать частоту каждого слова.Для этого вы можете использовать одномерный массив пар, где первое поле будет словом, а второе - его частотой.Вы сделали бы это, перебирая 2D-массив, получая его последнее поле (предложение), и разделяя эту строку (предложение) на пробелы.Затем для каждого слова вы проверяете, присутствует ли оно в массиве пар, если да, увеличиваете его частоту на единицу (поскольку вы уже видели это слово, теперь вы видели его снова).Если нет, вставьте его в этот массив и установите для него частоту 1, поскольку вы впервые увидели это слово.

Каков размер массива пар?Поскольку вы не хотите использовать std::vector, который автоматически позаботится о динамическом росте, так как вы будете вставлять в него элементы, вам нужно подумать об этом размере.

Поскольку число слов вCSV-файл неизвестен, вам нужно подумать о максимальном количестве слов в файле.Убедитесь, что это большой размер, чтобы можно было хранить все слова, которые вы увидите.С другой стороны, не устанавливайте его слишком большим, так как вы выделите слишком много памяти, что приведет к потере.

После установки размера вы будете использовать счетчик, который будет содержать фактическое числослов читать.Таким образом, вы будете знать значимый размер массива для себя, который вы будете использовать, когда вы захотите перебрать этот массив, например, для его печати. ​​


Затем высортировать массив.std::sort идеально подходит для этого, когда вы должны определить функцию для сравнения элементов массива, который вы хотите отсортировать.

Наконец, вы должны печатать только слова счастота больше единицы;это общие слова.


Собрав все воедино, мы получим:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;

// search in the array of pairs for the 'word'. Check only the first 'count' pairs.
int search_pair_in_array(const pair<string, int> wordFr[], const int count, const string word)
{
  for(int i = 0; i < count; ++i)
    if(wordFr[i].first == word)
      return i;
  return -1;
}

// compare function to be used by std::sort
bool pairCmp(const pair<string, int>& wordFr1, const pair<string, int>& wordFr2)
{ 
  return (wordFr1.second > wordFr2.second);
}

int main()
{
  // number of lines and number of tokens per line
  const int N = 3, M = 3;
  // line read from file, 2D array of lines read from line
  string line, lines[N][M];
  ifstream csvFile("myFile.csv");

  if(csvFile.is_open())
  {
    cout << "Successfully opened file"<<endl;

    int i = 0, j = 0;
    // read from 'csvFile', store to 'line', and use comma as the delimeter
    while(getline(csvFile, line, ','))
    {
      //cout << "|" << line << "|" << endl;
      size_t found = line.find("\n");
      if (found != std::string::npos) // if newline was found
      {
        string lastToken = line.substr(0, found);
        string nextLineFirstTOken = line.substr(found + 1);
        lines[i++][j] = lastToken.substr(1, lastToken.size() - 2);
        j = 0;
        if(nextLineFirstTOken != "") // when you read the last token of the last line          
          lines[i][j++] = nextLineFirstTOken.substr(1, nextLineFirstTOken.size() - 2);
      }
      else
      {
        // to not copy the double quotes from first and last character
        lines[i][j++] = line.substr(1, line.size() - 2);
      }
    }

    // for(int i = 0; i < N; ++i)
    // {
    //   for(int j = 0; j < M; ++j)
    //   {
    //     cout << lines[i][j] << " ";
    //   }
    //   cout << endl;
    // }

    // max number of words
    const int W = 100;
    // array of pairs that stores a word and its frequency per cell
    pair<string, int> wordFr[W];
    // number of words (to be updated totally after the for loop)
    int count = 0;
    // for every line of the 2D array
    for(int i = 0; i < N; ++i)
    {
      string word;
      // get the last field (the sentence) of the i-th line
      stringstream ss(lines[i][M - 1]);
      // split sentence to words (implicit delimeter: space)
      // for every word in the sentence, do:
      while (ss >> word)
      {
        //cout << word << " " << search_pair_in_array(wordFr, W, word) << endl;

        // check if word already in array of pairs
        int idx = search_pair_in_array(wordFr, W, word);
        // not found, insert the word in array of pairs, set its frequency to 1 (shown that word for first time)
        if(idx == -1)
          wordFr[count++] = make_pair(word, 1);
        // word found in array of pairs, increase it frequency by one
        else
          wordFr[idx].second++;
      }
    }

    // sort the array 'wordFr', by using 'pairCmp' as the compare function. Notice that we care only for the first 'count' elements of the array.
    sort (wordFr, wordFr + count, pairCmp);

    cout << "Word, Frequency\n";
    for(int i = 0; i < count; ++i)
      if(wordFr[i].second > 1) // print only common words (assuming that a word with frequency > 1 is present in another sentence too)
        cout << wordFr[i].first << ", " << wordFr[i].second << endl;
  }
  return 0;
}

Вывод:

Successfully opened file
Word, Frequency
I, 4
my, 3
to, 3
want, 2
tired, 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...