以下Python代码在来自Matlab背景时显得非常冗长
>>> a = [1, 2, 3, 1, 2, 3]
>>> [index for index,value in enumerate(a) if value > 2]
[2, 5]
在Matlab中我可以写:
>> a = [1, 2, 3, 1, 2, 3];
>> find(a>2)
ans =
3 6
是否有一种用Python编写的简便方法,或者我只是坚持使用长版本?
感谢您提供有关Python语法基本原理的所有建议和解释。
在numpy网站上找到以下内容之后,我想我找到了一个我喜欢的解决方案:
http://docs.scipy.org/doc/numpy/user/basics.indexing.html#boolean-or-mask-index-arrays
将该网站的信息应用于上述问题,将提供以下信息:
>>> from numpy import array
>>> a = array([1, 2, 3, 1, 2, 3])
>>> b = a>2
array([False, False, True, False, False, True], dtype=bool)
>>> r = array(range(len(b)))
>>> r(b)
[2, 5]
以下应该可以工作(但我手头没有Python解释器来测试它):
class my_array(numpy.array):
def find(self, b):
r = array(range(len(b)))
return r(b)
>>> a = my_array([1, 2, 3, 1, 2, 3])
>>> a.find(a>2)
[2, 5]
答案 0 :(得分:64)
在Python中,根本不会使用索引,只需处理值 - [value for value in a if value > 2]
。通常处理索引意味着你没有采取最好的方式。
如果您 需要类似于Matlab的API,您可以使用numpy,这是一个用于Python中多维数组和数值数学的包,它受Matlab的启发。您将使用numpy数组而不是列表。
>>> import numpy
>>> a = numpy.array([1, 2, 3, 1, 2, 3])
>>> a
array([1, 2, 3, 1, 2, 3])
>>> numpy.where(a > 2)
(array([2, 5]),)
>>> a > 2
array([False, False, True, False, False, True], dtype=bool)
>>> a[numpy.where(a > 2)]
array([3, 3])
>>> a[a > 2]
array([3, 3])
答案 1 :(得分:44)
另一种方式:
>>> [i for i in range(len(a)) if a[i] > 2]
[2, 5]
一般来说,请记住而find
是一个现成的功能,列表推导是一般的,因此非常强大的解决方案。没有什么能阻止您在Python中编写find
函数并在以后随意使用它。即:
>>> def find_indices(lst, condition):
... return [i for i, elem in enumerate(lst) if condition(elem)]
...
>>> find_indices(a, lambda e: e > 2)
[2, 5]
请注意,我在这里使用列表来模仿Matlab。使用生成器和迭代器会更加Pythonic。
答案 2 :(得分:13)
对我来说效果很好:
private void DetayButton_Click(object sender, RoutedEventArgs e)
{
DetayWindow pencere = new DetayWindow();
string sorgu = "Select * From Gayrimenkul";
DataSet dataSet = new DataSet();
SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter(sorgu, baglanti);
dataAdapter.Fill(dataSet);
int i = dataGrid1.SelectedIndex;
string veribaslik = dataSet.Tables[0].Rows[i]["baslik"].ToString();
string veriyazi = dataSet.Tables[0].Rows[i]["yazi"].ToString();
string veritarih = dataSet.Tables[0].Rows[i]["tarih"].ToString();
string verimevkii = dataSet.Tables[0].Rows[i]["mevkii"].ToString();
string verimetrekare = dataSet.Tables[0].Rows[i]["metrekare"].ToString();
string veritur = dataSet.Tables[0].Rows[i]["tur"].ToString();
string veriid = dataSet.Tables[0].Rows[i]["id"].ToString();
pencere.baslik = veribaslik;
pencere.yazi = veriyazi;
pencere.tarih = veritarih;
pencere.mevkii = verimevkii;
pencere.metrekare = verimetrekare;
pencere.tur = veritur;
pencere.id = veriid;
pencere.ShowDialog();
}
答案 3 :(得分:6)
也许另一个问题是,“一旦你得到它们,你会对这些指数做什么?”如果您打算使用它们来创建另一个列表,那么在Python中,它们是不必要的中间步骤。如果您想要所有与给定条件匹配的值,只需使用内置过滤器:
matchingVals = filter(lambda x : x>2, a)
或者编写自己的列表comprhension:
matchingVals = [x for x in a if x > 2]
如果你想从列表中删除它们,那么Pythonic方式不一定要从列表中删除,而是写一个列表理解,就好像你正在创建一个新列表一样,并使用{{{}进行就地分配。 1}}在左侧:
listvar[:]
Matlab提供a[:] = [x for x in a if x <= 2]
,因为它的以数组为中心的模型通过使用数组索引选择项目来工作。当然,可以在Python中执行此操作,但更多的Pythonic方法是使用迭代器和生成器,如@EliBendersky已经提到的那样。
答案 4 :(得分:5)
即使这是一个迟到的答案:我认为这仍然是一个非常好的问题,恕我直言Python(没有额外的库或像numpy这样的工具包)仍然缺乏一种方便的方法来根据手动定义的过滤器访问列表元素的索引
您可以手动定义一个提供该功能的功能:
def indices(list, filtr=lambda x: bool(x)):
return [i for i,x in enumerate(list) if filtr(x)]
print(indices([1,0,3,5,1], lambda x: x==1))
收益率:[0,4]
在我的想象中,完美的方法是制作一个子类列表并将索引函数添加为类方法。这样只需要过滤方法:
class MyList(list):
def __init__(self, *args):
list.__init__(self, *args)
def indices(self, filtr=lambda x: bool(x)):
return [i for i,x in enumerate(self) if filtr(x)]
my_list = MyList([1,0,3,5,1])
my_list.indices(lambda x: x==1)
我在这里详细阐述了这个话题: http://tinyurl.com/jajrr87