Есть ли альтернативный способ условно увеличить значения массива без использования операторов if? C ++

Ты был на правильном пути, когда решил перебирать разговоры. Попробуйте следующее:

conversations = Conversation.
  where("receiver = :user_id OR sender = :user_id", user_id: currenct_user.id)

Message.where(conversation: conversations).
  where.not(user: current_user).where(read: false).count

Я также предлагаю добавить область видимости unread в вашу модель сообщений для чтения,

class Message < ApplicationRecord
  ...
  scope :unread, -> { where(read: false) }
  ...
end

Теперь вы можете написать:

Message.where(conversation: conversations).
  where.not(user: current_user).unread.count
-3
задан πάντα ῥεῖ 18 January 2019 в 18:10
поделиться

5 ответов

Следующее имеет довольно некоторые шансы быть одним из самых быстрых в вопросах подсчета:

std::array<unsigned int, (1U << CHAR_BIT)> counts({ });
for(auto c : word)
    counts[c]++;

Получение отдельных значений довольно эффективно:

 std::cout << "a: " << counts['a'] << std::endl

Перебор букв - ну, потребуется небольшой трюк:

 for(char const* c = "abcdefghijklmnopqrstuvwxyz"; *c; ++c)
     // case-insensitive:
     std::cout << *c << ": " << counts[*c] + counts[toupper(*c)] << std::endl;

Конечно, вы тратите немного памяти - это может стоить вам производительности снова: если массив больше не помещается в кеш ...

0
ответ дан Aconcagua 18 January 2019 в 18:10
поделиться

Общее и переносимое решение было бы

const std::string alphabet = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; alphabet[i]; ++i)
      amounts[i] = std::count(word.begin(), word.end(), alphabet[i]);

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

for (char c = 'a'; c <= 'z'; ++c)
    amounts[c - 'a'] = std::count(word.begin(), word.end(), c);

Нет (открытый ) if выше. Конечно, ничто не мешает реализации std::count() с его использованием.

0
ответ дан Peter 18 January 2019 в 18:10
поделиться

Используйте std :: unordered_map < std :: string, int> . Обратите внимание, что std :: unordered_map < char, int> будет более эффективным, если требуется только один символ. std :: string позволяет подсчитывать сложные строки (например, map ["substring"] ++)

К картам можно обращаться, используя скобочные обозначения (например, map [index]), и, таким образом, можно эффективно устранить необходимость использования операторов if .

#include <string>
#include <unordered_map>
#include <iostream>

int main()
{
    std::unordered_map< std::string, int > map = {  {"a",0} };
    map["a"] += 1;
    std::cout << map["a"];
}
0
ответ дан WeRelic 18 January 2019 в 18:10
поделиться

Что вы хотите:

const char char_offset = 'a';
const int num_chars = 26;
std::vector<int> amounts(num_chars, 0);
std::string word = "blahblah";

for (auto c : word) {
  int i = c - char_offset;
  // this if statement is only for range checking.
  // you can remove it if you are sure about the data range.
  if (i >= 0 && i < num_chars) { 
    ++amounts[i];
  }
}

for (int i = 0; i < (int)amounts.size(); ++i) {
  std::cout << (char)(char_offset + i) << ": " << amounts[i] << std::endl;
}
<час>
Output
a: 2
b: 2
c: 0
d: 0
e: 0
f: 0
g: 0
h: 2
i: 0
j: 0
k: 0
l: 2
m: 0
n: 0
...
0
ответ дан eosphorox 18 January 2019 в 18:10
поделиться

Учитывая ваш пример, предполагая, что вся строка состоит из строчных букв и допустимых символов, существует довольно простое решение (то есть вы обрабатываете проверку)

for (int i = 0; i < word.size(); i++) {
    amounts[word[i]-'a']++; // you can also do a pre-increment if you want
}
0
ответ дан Daniel 18 January 2019 в 18:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: