Python: выбор элементов из списка с использованием списка [duplicate]

Когда объекту класса Derived присвоен объект Base class Object, все члены объекта производного класса копируются в объект базового класса, за исключением членов, которых нет в базовом классе. Эти члены удаляются компилятором. Это называется Object Slicing.

Вот пример:

#include<bits/stdc++.h>
using namespace std;
class Base
{
    public:
        int a;
        int b;
        int c;
        Base()
        {
            a=10;
            b=20;
            c=30;
        }
};
class Derived : public Base
{
    public:
        int d;
        int e;
        Derived()
        {
            d=40;
            e=50;
        }
};
int main()
{
    Derived d;
    cout<<d.a<<"\n";
    cout<<d.b<<"\n";
    cout<<d.c<<"\n";
    cout<<d.d<<"\n";
    cout<<d.e<<"\n";


    Base b = d;
    cout<<b.a<<"\n";
    cout<<b.b<<"\n";
    cout<<b.c<<"\n";
    cout<<b.d<<"\n";
    cout<<b.e<<"\n";
    return 0;
}

Он будет генерировать:

[Error] 'class Base' has no member named 'd'
[Error] 'class Base' has no member named 'e'
148
задан hoang tran 16 August 2013 в 12:22
поделиться

6 ответов

Вы можете использовать operator.itemgetter :

from operator import itemgetter 
a = [-2, 1, 5, 3, 8, 5, 6]
b = [1, 2, 5]
print itemgetter(*b)(a)
# Result:
(1, 5, 5)

Или вы можете использовать numpy :

import numpy as np
a = np.array([-2, 1, 5, 3, 8, 5, 6])
b = [1, 2, 5]
print list(a[b])
# Result:
[1, 5, 5]

Но на самом деле, ваше текущее решение в порядке. Вероятно, это самый лучший из всех.

130
ответ дан FatihAkici 20 August 2018 в 19:47
поделиться
  • 1
    +1, отметив, что c = [a[i] for i in b] отлично. Обратите внимание, что решение itemgetter не будет делать то же самое, если b имеет менее 2 элементов. – flornquake 16 August 2013 в 12:35
  • 2
    Сторона Примечание : Использование itemgetter во время работы в многопроцессорном режиме не работает. Numpy отлично работает в многопроцессорном режиме. – Lior Magen 29 March 2016 в 10:26
  • 3
    Дополнительный комментарий a[b] работает только , когда a является массивом numpy , т. Е. Вы создаете его с помощью функции numpy. – Ludwig Zhou 7 August 2017 в 09:11
  • 4
    Я сравнивал параметры без numpy и itemgetter, кажется, самый быстрый, даже немного быстрее, чем просто набирать нужные индексы внутри круглых скобок, используя Python 3.44 – citizen2077 16 October 2017 в 09:42

Другое решение может быть через pandas Series:

import pandas as pd

a = pd.Series([-2, 1, 5, 3, 8, 5, 6])
b = [1, 2, 5]
c = a[b]

Вы можете преобразовать c обратно в список, если хотите:

c = list(c)
3
ответ дан BossaNova 20 August 2018 в 19:47
поделиться

Базовое и не очень обширное тестирование, сравнивающее время выполнения пяти предоставленных ответов:

def numpyIndexValues(a, b):
    na = np.array(a)
    nb = np.array(b)
    out = list(na[nb])
    return out

def mapIndexValues(a, b):
    out = map(a.__getitem__, b)
    return list(out)

def getIndexValues(a, b):
    out = operator.itemgetter(*b)(a)
    return out

def pythonLoopOverlap(a, b):
    c = [ a[i] for i in b]
    return c

multipleListItemValues = lambda searchList, ind: [searchList[i] for i in ind]

с использованием следующего ввода:

a = range(0, 10000000)
b = range(500, 500000)

простой цикл питона был самым быстрым с лямбда-операцией, близкой секунде, mapIndexValues ​​и getIndexValues ​​были последовательно похожи на метод numpy значительно медленнее после преобразования списков в массивы numpy. Если данные уже находятся в массивах numpy, метод numpyIndexValues ​​с удалением numpy.array удаляется быстрее.

numpyIndexValues -> time:1.38940598 (when converted the lists to numpy arrays)
numpyIndexValues -> time:0.0193445 (using numpy array instead of python list as input, and conversion code removed)
mapIndexValues -> time:0.06477512099999999
getIndexValues -> time:0.06391049500000001
multipleListItemValues -> time:0.043773591
pythonLoopOverlap -> time:0.043021754999999995
3
ответ дан Don Smythe 20 August 2018 в 19:47
поделиться
  • 1
    Я не знаю, какой интерпретатор Python вы используете, но первый метод numpyIndexValues не работает, поскольку a, b имеют тип range. Я предполагаю, что вы сначала конвертируете a, b в numpy.ndarrays? – strpeter 14 October 2015 в 08:21
  • 2
    @strpeter Да, я не сравнивал яблоки с яблоками, я создал массивы numpy в качестве входных данных в тестовом примере для numpyIndexValues. Я исправил это сейчас, и все они используют те же списки, что и вход. – Don Smythe 18 October 2015 в 05:23

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

c = [a[b[0]]] + [a[b[1]]] + [a[b[2]]]

Или даже проще, если сами индексы являются константами ...

c = [a[1]] + [a[2]] + [a[5]]

Или, если существует последовательный диапазон индексов ...

c = a[1:3] + [a[5]]
2
ответ дан ecp 20 August 2018 в 19:47
поделиться
  • 1
    Спасибо, что напомнили мне, что [a] + [b] = [a, b] – onewhaleid 3 May 2017 в 23:57

Мой ответ не использует коллекции numpy или python.

Один тривиальный способ найти элементы:

a = [-2, 1, 5, 3, 8, 5, 6]
b = [1, 2, 5]
c = [i for i in a if i in b]

Недостаток: этот метод может не быть работайте для больших списков. Использование numpy рекомендуется для больших списков.

28
ответ дан falsetru 20 August 2018 в 19:47
поделиться
  • 1
    Не нужно итерации a. [a[i] for i in b] – falsetru 22 September 2014 в 13:38
  • 2
    Этот метод даже не работает ни в одном другом случае. Что, если в a было еще 5? – TerryA 21 July 2015 в 21:47
  • 3
    IMO, быстрее выполнить такое пересечение с помощью множеств – sirgogo 15 March 2017 в 22:13
  • 4
    Если вы беспокоитесь об IndexErrors, если b имеет номера, превышающие размер, попробуйте [a[i] if i<len(a) else None for i in b] – 576i 9 August 2018 в 09:23
29
ответ дан falsetru 31 October 2018 в 15:04
поделиться
Другие вопросы по тегам:

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