#c #python #arrays
#c #python #массивы
Вопрос:
Я пытаюсь найти лучшую библиотеку / пакет C для манипулирования массивами в стиле python. В принципе, мне нужна простота, подобная этой:
values = numpy.array(inp.data)
idx1 = numpy.where(values > -2.14)
idx2 = numpy.where(values < 2.0)
res1 = (values[idx1] - diff1)/1000
res2 = (values[idx2] - diff2)*1000
В python это всего лишь 5 строк, но самый простой способ в C , который я могу придумать, — это довольно большое количество вложенных циклов. Пожалуйста, дайте совет..
В основном мой вопрос касается операций с массивами / векторами, таких как умножение массивов, операции с индексами и т.д.. В приведенном выше примере res1 представляет собой массив, содержащий набор элементов, отфильтрованных из массива значений, и некоторую арифметику, применяемую впоследствии (вычитание, умножение для всех выбранных элементов). В этом примере на python я не копирую элементы массива values, поскольку он может быть достаточно большим с точки зрения объема памяти, я сохраняю только индексы и хочу иметь возможность выполнять арифметические операции над выбранным набором элементов исходного массива.
Комментарии:
1. Пожалуйста, объясните, что делает код Python, для тех из нас, кто не знаком с numpy.
2. просто расширил мой вопрос более подробным объяснением
3. Просто для ясности, вы ищете решение не из стандартной библиотеки C (потому что ее нет, так же как numpy не является частью стандартной библиотеки Python), вы ищете хорошую стороннюю математическую библиотеку, способную манипулировать массивами, подобными numpy? (Я не знаю ни одного, но сомневаюсь, что он будет таким же кратким со всеми объявлениями и т.д.)
Ответ №1:
Вам вообще не следует использовать массивы. Пожалуйста, сядьте и узнайте о классе std::vector, а также об итераторах и алгоритмах стандартной библиотеки. Я настоятельно рекомендую прочитать книгу The C Standard Library.
Комментарии:
1. То, что плакат называет «массивами», не обязательно является массивами C, это общая концепция.
2. @ static_rtti Термин «массив» в C имеет конкретное техническое значение.
Ответ №2:
Вы можете достичь чего-то подобного в C , но вам не следует использовать для этого простые массивы C .
Самый простой способ, которым я могу представить эту работу, — использовать std::set
число с плавающей точкой (похоже, что ваш код предполагает, что данные отсортированы в порядке возрастания). Вы также могли бы использовать std::vector
из float, но вам придется сортировать это самостоятельно, вероятно, с помощью std::sort
.
В этом случае ваш пример кода может выглядеть следующим образом — набор предполагает, что значения уникальны, если это не так, вы могли бы использовать std::multiset
вместо;
std::set<float> values(inp.data.begin(), inp.data.end());
std::set<float>::iterator idx1 = values.lower_bound(-2.14);
std::set<float>::iterator idx2 = values.upper_bound(2.0);
float res1 = (*idx1 - diff1) / 1000.0;
float res2 = (*idx2 - diff2) / 1000.0;
Пожалуйста, обратите внимание, что приведенный выше пример кода не является 100% преобразованием вашего исходного кода — lower_bound
дает вам первый элемент, который равен или больше -2.14. Я также не вводил никакого кода проверки на наличие сбоев — например, если lower_bound
или upper_bound
не удается найти соответствующие элементы, они будут возвращены values.end()
.
Используя vector, пример будет выглядеть очень похоже, всего на одну строку больше для предварительной сортировки вектора:
std::vector<float> values(inp.data.begin(), inp.data.end());
std::sort(values.begin(), values.end();
std::vector<float>::iterator idx1 = std::lower_bound(values.begin(), values.end(), -2.14);
std::vector<float>::iterator idx2 = std::upper_bound(values.begin(), values.end(), 2.0);
float res1 = (*idx1 - diff1) / 1000.0;
float res2 = (*idx2 - diff2) / 1000.0;
Комментарии:
1. Это действительно хороший пример, но не совсем то, что я ищу. По сути, в моем примере с python res1 также является массивом, а выражение — векторной операцией. Это означает, что в C я должен поместить все это в 2 цикла, например while(idx1 != values.end) { res1.push_back((*idx1 — diff1)/1000); }; while(idx2 != values.end) { res2.push_back((*idx2 — diff2)/1000); };
2. А, ладно. Я думаю, это помогло бы, если бы я говорил на Python :). Вы могли бы скрыть циклы, используя что-то вроде std::copy и скопировать их через функтор с обратным вставщиком, но это скрывает цикл больше, чем что-либо еще.
Ответ №3:
Я предлагаю вам проверить заголовок алгоритма. Также не работают с массивами, у вас есть std::vector или boost (скоро будет std)::array.
Ответ №4:
Если я не ошибаюсь, numpy написан в основном на C (с оболочкой Python), так что вы могли бы использовать его непосредственно из C без особых усилий.
Ответ №5:
Если вы объедините std::vector
и boost::lambda
, вы можете действительно приблизиться к вашему примеру:
#include <algorithm>
#include <iostream>
#include <vector>
#include <boost/lambda/lambda.hpp>
using boost::lambda::_1;
int main() {
float ary[10] = { -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 };
std::vector<float> v(amp;ary[0], amp;ary[10]);
std::vector<float>::iterator iter1, iter2;
iter1 = std::find_if(v.begin(), v.end(), (_1 > -2.14));
iter2 = std::find_if(v.begin(), v.end(), (_1 < 2.0));
// output:
// iter1 = -2.000
// iter2 = 1.000
std::cout
<< "iter1 = " << *iter1 << "n"
<< "iter2 = " << *iter2 << "n"
<< std::endl;
return 0;
}
Комментарии:
1. То же, что и выше. Эта первая часть работает нормально, но как насчет векторных операций, таких как res_vector = (v[iter1] — fixed_value) * 1000 ?
2. Только если под «действительно близким» вы подразумеваете «в десять раз более подробный» 🙂
3. @static_rtti: большая часть подробностей связана с настройкой и печатью. В примере python опущен
import numpy
и не включен параметр печати. Но да, более подробно включать явный ввод и другую статическую информацию. Основная обработка внутриmain
практически такая же.