2012-02-20 4 views
2

Я попытался получить домашний сайт URL-адреса. Во-первых, я использовал цикл for и достиг цели.Почему python reduce() пропускает элемент None?

home = '' 
my_url = 'http://www.mysite.com/subdir/subdir2/index.html' 
for item in my_url.split('/')[:3]: 
    home += item + '/' 
print home 

и я могу получить

'http://www.mysite.com/' 

Тогда я сталкиваюсь уменьшить(), который я никогда не использовал раньше. Так что я получаю это выстрел, вот код:

my_url = 'http://www.mysite.com/subdir/subdir2/index.html' 
home = '' 
home = reduce(lambda x,y : x + y + '/',my_url.split('/')[:3]) 
print home 

на этот раз я получил

'http:/www.mysite.com/' 

ли это уменьшить не только ommit в None в нем Что объяснение результата?

да, я знаю из this topic, что я мог бы просто использовать функцию синтаксического анализа URLLIB, чтобы сделать это, так что я надеюсь, что здесь обсуждение будет сосредоточено на уменьшения()

+0

вы должны использовать filter() для удаления None elements – sherpya

+0

@sherpya Нет, я не хочу пропустить элемент None, я смущен тем, что функция reduce() пропускает элемент None и оставляет результат как «http: /www.mysite.com/ ', который должен быть «http://www.mysite.com/» –

+0

'reduce' ничего не пропускает. Элемента 'None' нет. Где, по вашему мнению, это происходит? –

ответ

6
my_url = 'http://www.mysite.com/subdir/subdir2/index.html' 
home = '' 
home = reduce(lambda x,y : x + y + '/',my_url.split('/')[:3]) 

my_url.split('/')[:3] #=> ['http:', '', 'www.mysite.com'] 

'http:' + '' + '/' #=> 'http:/' 
'http:/' + 'www.mysite.com' + '/' #=> 'http:/www.mysite.com/' 

Это не таинственно. Все работает так, как ожидалось - проблема в том, что URL-адреса не являются однородными, поскольку протокол разделяется двойной косой чертой.

Полезный инструмент для понимания того, как сократить работы является scanl от functional (http://pypi.python.org/pypi/functional):

In [11]: home = scanl(lambda x,y : '%s%s/'%(x,y),my_url.split('/')[0],my_url.split('/')[1:3]) 

In [12]: home 
Out[12]: <generator object _scanl at 0x0000000003DEC828> 

In [13]: list(home) 
Out[13]: ['http:', 'http:/', 'http:/www.mysite.com/'] 

Обратите внимание, что str.join реализует несколько иной алгоритм:

In [16]: '/'.join(my_url.split('/')) 
Out[16]: 'http://www.mysite.com/subdir/subdir2/index.html' 

Это то, что люди обычно хотят - это равнозначно:

In [22]: reduce(lambda x,y : '%s/%s'%(x,y),my_url.split('/')) 
Out[22]: 'http://www.mysite.com/subdir/subdir2/index.html' 
+1

Это точное объяснение! Спасибо ~ –

+0

@ user1117789: Без проблем. Также см. Мое обновление re scanl – Marcin

+0

На самом деле, «URL-адреса не являются однородными», это не проблема. Подход с 'reduce' работает", если мы вместо этого выполняем lambda x, y: x + '/' + y', так что косые черты помещаются между компонентами, а не после каждого, кроме первого. Конечно, таким образом в конце не будет косой черты. –

2

да, я знаю, что из этой темы, что я могли бы просто использовать функцию синтаксического анализа URLLIB, чтобы сделать это, так что я надеюсь, что здесь обсуждение фокус на снижения()

Я не понимаю, почему вы хотите, чтобы изобретать колесо, если есть функция в стандартной библиотеке в Сделай так. Я действительно предлагаю вам не тратить время и ознакомиться с стандартной библиотекой pythons и использовать предоставленные функции.

В любом случае, возвращаясь к вашему вопросу: Когда я тип: my_url.split('/')[:3] я получаю это:

['http:', '', 'www.mysite.com'] 

Так что нет в нем нет None, просто пустая строка, которая может быть использована как и любой другой строки. И, по-видимому, это то, что делает ваша лямбда-функция для алгоритма reduce, она просто объединяет строки обратно вместе. Я предлагаю вам использовать метод stringsjoin, так как он более читаемый и легко объясним:

>>> parts = my_url.split('/')[:3] 
>>> print "/".join(parts) 
'http://www.mysite.com' 

Вы должны добавить в последнем / себя, хотя.

+0

благодарит Константина. Я просто пытаюсь найти какой-то случай, который может уменьшить(). Поскольку я знаю, что для этого уже требуется urllib, мне не нужно будет использовать этот «колесо». –