Игнорируйте регистр в строках Python [дубликат]

Я также боролся с этой ошибкой и оказался в той же стратегии, что и ответ. Я включаю свой ответ, чтобы подтвердить, что это стратегия, которая должна работать.

Вот пример, когда я делаю сначала одно внутреннее соединение между двумя таблицами, которые, как я знаю, получил данные, а затем два левых внешних соединения на таблицах, которые могут иметь соответствующие строки, которые могут быть пустыми. Вы смешиваете внутренние соединения и внешние соединения, чтобы получать результаты с данными по таблицам вместо того, чтобы делать синтаксис по умолчанию, разделенный запятой между таблицами, и пропускать строки в желаемом соединении.

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]%')

Сначала: Внутренние соединения между таблицами, которые, как вы ожидаете, будут соответствовать данным. Вторая часть. Продолжайте использовать внешние соединения, чтобы попытаться получить данные в других таблицах, но это не будет отфильтровывать ваш результирующий набор, если внешнее соединение таблицы не имеет соответствующих данных или соответствует условию, которое вы настроили в предикате / состоянии.

51
задан tzot 26 November 2008 в 02:20
поделиться

14 ответов

В ответ на Ваше разъяснение...

Вы могли использовать 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: Нечувствительные к регистру Строки являются рецептом для создания нечувствительного к регистру строкового класса. Это могло бы быть закончено уничтожения для чего-то быстрого, но могло предоставить Вам распространенный способ обработать нечувствительные к регистру строки, если Вы планируете использование их часто.

-12
ответ дан patrickyoung 7 November 2019 в 20:11
поделиться

Когда что-то плохо поддерживается в стандартной библиотеке, я всегда ищу пакет 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

Так как я использовал совпадение вместо поиска, мне не нужно было добавлять курсор (^) к регулярному выражению.

Примечание: Это только проверка равенства, что иногда бывает необходимо. Я бы также не стал говорить, что мне это нравится.

2
ответ дан 7 November 2019 в 10:11
поделиться

Вы могли разделить на подклассы str и создать свой собственный строковый класс случая-insenstive, но по моему скромному мнению который будет чрезвычайно неблагоразумен и создаст намного больше проблемы, чем это стоит.

-1
ответ дан Dave Webb 7 November 2019 в 20:11
поделиться

Просто используйте str().lower() метод, если не высокоэффективный важно - в этом случае пишут что метод сортировки как расширение C.

, "Как записать, Расширение Python" походит на достойное введение..

более интересно, Это руководство сравнивает пользование ctypes библиотекой по сравнению с записью внешнего модуля C (ctype вполне существенно медленнее, чем расширение C).

0
ответ дан dbr 7 November 2019 в 20:11
поделиться

Вы могли перевести каждую строку в нижний регистр однажды---лениво только при необходимости в нем, или как в предварительной передаче в вид, если Вы знаете о сортировке всего набора строк. Существует несколько способов присоединить этот ключ сравнения к фактическим отсортированным данным, но эти методы должны быть обращены в отдельном вопросе.

Примечание, что эта техника может использоваться не только для обработки верхних проблем / проблем нижнего регистра, но и для других типов сортировки, таких как локаль определенная сортировка или заголовок "стиля Библиотеки", сортирующий, который игнорирует передовицы и иначе нормализует данные прежде, чем отсортировать их.

0
ответ дан Dale Wilson 7 November 2019 в 20:11
поделиться

Для случайных или даже повторных сравнений несколько дополнительных строковых объектов не должны иметь значения, пока этого не произойдет в самом внутреннем цикле Вашего базового кода, или у Вас нет достаточного количества данных для фактического замечания влияния производительности. Посмотрите, делаете ли Вы: выполнение вещей "глупым" способом намного менее глупо, если Вы также делаете это меньше.

, Если Вы серьезно хотите продолжать сравнивать партии и много текста нечувствительно к регистру, Вы могли бы так или иначе сохранить строчные версии строк под рукой, чтобы избежать завершения и воссоздания, или нормализовать целый набор данных в нижний регистр. Это, конечно, зависит от размера набора данных. Если существует относительно небольшое количество иглы и большой стог сена, замена игл со скомпилированными объектами RegExp является одним решением. Если трудно сказать, не видя конкретного примера.

0
ответ дан 7 November 2019 в 20:11
поделиться

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

0
ответ дан Mark Biek 7 November 2019 в 20:11
поделиться

Это - то, как Вы сделали бы это с ре:

import re
p = re.compile('^hello, re.I)
p.match('Hello')
p.match('hello')
p.match('HELLO')
1
ответ дан Moses Ting 7 November 2019 в 20:11
поделиться

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

>>> 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, таким образом, они могут использоваться в качестве ключей словаря, элементов множества, и т.д.

1
ответ дан Antoine P. 7 November 2019 в 20:11
поделиться

Нет никакого встроенного эквивалента той функции, которую Вы хотите.

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

, Если Вы не работаете с чрезвычайно длинными строками (так долго, который может вызвать проблему памяти, если бы дублировано) тогда я сохранил бы ее простой и использование

str1.lower() == str2.lower()

, Вы будете в порядке

3
ответ дан Benjamin 7 November 2019 в 20:11
поделиться

Я не могу найти никакой другой встроенный способ сделать нечувствительное к регистру сравнение: рецепт поваренной книги Python использует ниже ().

Однако необходимо быть осторожными при использовании ниже для сравнений из-за турецкий язык I проблем . К сожалению, обработка Python для турецкого языка, не хорошо. Д± преобразовывается в меня, но я не преобразовываюсь в Д±. ° Д преобразовывается в меня, но я не преобразовываюсь в Д °.

5
ответ дан Douglas Leeder 7 November 2019 в 20:11
поделиться

Вы используете, это выдерживает сравнение в 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

7
ответ дан twasbrillig 7 November 2019 в 20:11
поделиться

Ваш вопрос подразумевает, что Вам не нужен 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.

7
ответ дан tzot 7 November 2019 в 20:11
поделиться

Вот сравнительный тест, показывающий, что использование 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 контексте.

75
ответ дан 7 November 2019 в 20:11
поделиться
Другие вопросы по тегам:

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