Я также боролся с этой ошибкой и оказался в той же стратегии, что и ответ. Я включаю свой ответ, чтобы подтвердить, что это стратегия, которая должна работать.
Вот пример, когда я делаю сначала одно внутреннее соединение между двумя таблицами, которые, как я знаю, получил данные, а затем два левых внешних соединения на таблицах, которые могут иметь соответствующие строки, которые могут быть пустыми. Вы смешиваете внутренние соединения и внешние соединения, чтобы получать результаты с данными по таблицам вместо того, чтобы делать синтаксис по умолчанию, разделенный запятой между таблицами, и пропускать строки в желаемом соединении.
use somedatabase
go
select o.operationid, o.operatingdate, p.pasid, p.name as patientname, o.operationalunitid, f.name as operasjonsprogram, o.theaterid as stueid, t.name as stuenavn, o.status as operasjonsstatus from operation o
inner join patient p on o.operationid = p.operationid
left outer join freshorganizationalunit f on f.freshorganizationalunitid = o.operationalunitid
left outer join theater t on t.theaterid = o.theaterid
where (p.Name like '%Male[0-9]%' or p.Name like '%KFemale [0-9]%')
Сначала: Внутренние соединения между таблицами, которые, как вы ожидаете, будут соответствовать данным. Вторая часть. Продолжайте использовать внешние соединения, чтобы попытаться получить данные в других таблицах, но это не будет отфильтровывать ваш результирующий набор, если внешнее соединение таблицы не имеет соответствующих данных или соответствует условию, которое вы настроили в предикате / состоянии.
В ответ на Ваше разъяснение...
Вы могли использовать ctypes для выполнения функции c "strcasecmp". Ctypes включен в Python 2.5. Это обеспечивает способность обратиться к dll и совместно использованным библиотекам, таким как libc. Вот быстрый пример (Python на Linux; см. ссылку для справки Win32):
from ctypes import *
libc = CDLL("libc.so.6") // see link above for Win32 help
libc.strcasecmp("THIS", "this") // returns 0
libc.strcasecmp("THIS", "THAT") // returns 8
может также хотеть к ссылке strcasecmp документация
Едва ли уверенный, что это немного быстрее, или медленнее (не протестировали), но это - способ использовать функцию C, чтобы сделать нечувствительные к регистру сравнения строк.
Код ~~~~~~~~~~~~~~
ActiveState - Рецепт 194371: Нечувствительные к регистру Строки являются рецептом для создания нечувствительного к регистру строкового класса. Это могло бы быть закончено уничтожения для чего-то быстрого, но могло предоставить Вам распространенный способ обработать нечувствительные к регистру строки, если Вы планируете использование их часто.
Когда что-то плохо поддерживается в стандартной библиотеке, я всегда ищу пакет PyPI. С виртуализацией и повсеместным распространением современных дистрибутивов Linux я больше не избегаю расширений Python. PyICU, кажется, отвечает всем требованиям: https://stackoverflow.com/a/1098160/3461
Теперь есть вариант, который является чистым питоном. Он хорошо протестирован: https://github.com/jtauber/pyuca
Старый ответ:
Мне нравится решение с регулярными выражениями. Вот функцию, которую вы можете скопировать и вставить в любую функцию благодаря поддержке блочной структуры Python.
def equals_ignore_case(str1, str2):
import re
return re.match(re.escape(str1) + r'\Z', str2, re.I) is not None
Так как я использовал совпадение вместо поиска, мне не нужно было добавлять курсор (^) к регулярному выражению.
Примечание: Это только проверка равенства, что иногда бывает необходимо. Я бы также не стал говорить, что мне это нравится.
Вы могли разделить на подклассы str
и создать свой собственный строковый класс случая-insenstive, но по моему скромному мнению который будет чрезвычайно неблагоразумен и создаст намного больше проблемы, чем это стоит.
Просто используйте str().lower()
метод, если не высокоэффективный важно - в этом случае пишут что метод сортировки как расширение C.
, "Как записать, Расширение Python" походит на достойное введение..
более интересно, Это руководство сравнивает пользование ctypes библиотекой по сравнению с записью внешнего модуля C (ctype вполне существенно медленнее, чем расширение C).
Вы могли перевести каждую строку в нижний регистр однажды---лениво только при необходимости в нем, или как в предварительной передаче в вид, если Вы знаете о сортировке всего набора строк. Существует несколько способов присоединить этот ключ сравнения к фактическим отсортированным данным, но эти методы должны быть обращены в отдельном вопросе.
Примечание, что эта техника может использоваться не только для обработки верхних проблем / проблем нижнего регистра, но и для других типов сортировки, таких как локаль определенная сортировка или заголовок "стиля Библиотеки", сортирующий, который игнорирует передовицы и иначе нормализует данные прежде, чем отсортировать их.
Для случайных или даже повторных сравнений несколько дополнительных строковых объектов не должны иметь значения, пока этого не произойдет в самом внутреннем цикле Вашего базового кода, или у Вас нет достаточного количества данных для фактического замечания влияния производительности. Посмотрите, делаете ли Вы: выполнение вещей "глупым" способом намного менее глупо, если Вы также делаете это меньше.
, Если Вы серьезно хотите продолжать сравнивать партии и много текста нечувствительно к регистру, Вы могли бы так или иначе сохранить строчные версии строк под рукой, чтобы избежать завершения и воссоздания, или нормализовать целый набор данных в нижний регистр. Это, конечно, зависит от размера набора данных. Если существует относительно небольшое количество иглы и большой стог сена, замена игл со скомпилированными объектами RegExp является одним решением. Если трудно сказать, не видя конкретного примера.
Я вполне уверен Вы, любой должен использовать .lower () или использовать регулярное выражение. Я не знаю о встроенной нечувствительной к регистру функции сравнения строк.
Это - то, как Вы сделали бы это с ре:
import re
p = re.compile('^hello, re.I)
p.match('Hello')
p.match('hello')
p.match('HELLO')
Рекомендуемая идиома для сортировки списков значений с помощью дорого вычисляемых ключей к так называемому "украшенному шаблону". Это состоит просто в создании списка (ключ, значение) кортежи из исходного списка и вид тот список. Тогда это тривиально, чтобы устранить ключи и получить список отсортированных значений:
>>> original_list = ['a', 'b', 'A', 'B']
>>> decorated = [(s.lower(), s) for s in original_list]
>>> decorated.sort()
>>> sorted_list = [s[1] for s in decorated]
>>> sorted_list
['A', 'a', 'B', 'b']
Или если Вам нравятся остроты:
>>> sorted_list = [s[1] for s in sorted((s.lower(), s) for s in original_list)]
>>> sorted_list
['A', 'a', 'B', 'b']
, Если Вы действительно волнуетесь о стоимости вызова ниже (), можно просто сохранить кортежи (пониженная строка, исходная строка) везде. Кортежи являются самым дешевым видом контейнеров в Python, они также hashable, таким образом, они могут использоваться в качестве ключей словаря, элементов множества, и т.д.
Нет никакого встроенного эквивалента той функции, которую Вы хотите.
можно записать собственную функцию, которая преобразовывает в .lower () каждый символ за один раз, чтобы не копировать обе строки, но я уверен, что это будет очень интенсивный CPU и чрезвычайно неэффективный.
, Если Вы не работаете с чрезвычайно длинными строками (так долго, который может вызвать проблему памяти, если бы дублировано) тогда я сохранил бы ее простой и использование
str1.lower() == str2.lower()
, Вы будете в порядке
Я не могу найти никакой другой встроенный способ сделать нечувствительное к регистру сравнение: рецепт поваренной книги Python использует ниже ().
Однако необходимо быть осторожными при использовании ниже для сравнений из-за турецкий язык I проблем . К сожалению, обработка Python для турецкого языка, не хорошо. Д± преобразовывается в меня, но я не преобразовываюсь в Д±. ° Д преобразовывается в меня, но я не преобразовываюсь в Д °.
Вы используете, это выдерживает сравнение в very-frequently-executed пути highly-performance-sensitive приложения? С другой стороны, Вы выполняете это на строках, которые являются мегабайтами в размере? В противном случае тогда Вы не должны волноваться о производительности и просто использовать .lower () метод.
следующий код демонстрирует, что выполнение нечувствительного к регистру выдерживает сравнение путем вызова .lower () на двух строках, которые являются каждым, какой почти мегабайт в размере занимает приблизительно 0,009 секунды на моем настольном компьютере на 1.8 ГГц:
from timeit import Timer
s1 = "1234567890" * 100000 + "a"
s2 = "1234567890" * 100000 + "B"
code = "s1.lower() < s2.lower()"
time = Timer(code, "from __main__ import s1, s2").timeit(1000)
print time / 1000 # 0.00920499992371 on my machine
, Если действительно это - чрезвычайно значительный, критический по отношению к производительности раздел кода, то я рекомендую писать функцию в C и назвать его от Вашего кода Python, так как это позволит Вам делать действительно эффективный поиск без учета регистра. Детали о записи C дополнительные модули могут быть найдены здесь: https://docs.python.org/extending/extending.html
Ваш вопрос подразумевает, что Вам не нужен Unicode. Попробуйте следующий фрагмент кода; если это работает на Вас, Вы сделаны:
Python 2.5.2 (r252:60911, Aug 22 2008, 02:34:17)
[GCC 4.3.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.setlocale(locale.LC_COLLATE, "en_US")
'en_US'
>>> sorted("ABCabc", key=locale.strxfrm)
['a', 'A', 'b', 'B', 'c', 'C']
>>> sorted("ABCabc", cmp=locale.strcoll)
['a', 'A', 'b', 'B', 'c', 'C']
Разъяснение: в случае, если это не очевидно на первый взгляд, locale.strcoll, кажется, функция, в которой Вы нуждаетесь, избегая str.lower или строк "дубликата" locale.strxfrm.
Вот сравнительный тест, показывающий, что использование str.lower
быстрее, чем предложенный метод принятого ответа (libc.strcasecmp
):
#!/usr/bin/env python2.7
import random
import timeit
from ctypes import *
libc = CDLL('libc.dylib') # change to 'libc.so.6' on linux
with open('/usr/share/dict/words', 'r') as wordlist:
words = wordlist.read().splitlines()
random.shuffle(words)
print '%i words in list' % len(words)
setup = 'from __main__ import words, libc; gc.enable()'
stmts = [
('simple sort', 'sorted(words)'),
('sort with key=str.lower', 'sorted(words, key=str.lower)'),
('sort with cmp=libc.strcasecmp', 'sorted(words, cmp=libc.strcasecmp)'),
]
for (comment, stmt) in stmts:
t = timeit.Timer(stmt=stmt, setup=setup)
print '%s: %.2f msec/pass' % (comment, (1000*t.timeit(10)/10))
типичные времена на моей машине:
235886 words in list
simple sort: 483.59 msec/pass
sort with key=str.lower: 1064.70 msec/pass
sort with cmp=libc.strcasecmp: 5487.86 msec/pass
Так, версия с str.lower
не является только самой быстрой безусловно, но также и самой портативной и pythonic всех предлагаемых решений здесь. Я не представил использование памяти, но исходный плакат все еще не привел неопровержимую причину для волнения об этом. Кроме того, кто говорит, что вызов в libc модуль не копирует строк?
нбар: lower()
строковый метод также имеет преимущество того, чтобы быть зависимым от локали. Что-то Вы не будете, вероятно, разбираться при записи собственного "оптимизированного" решения. Несмотря на это, из-за ошибок и недостающих возможностей в Python, этот вид сравнения может дать Вам неправильные результаты в unicode контексте.