2017-11-29 4 views
2

목록을 포함하는 목록에서 정렬 다음 for 루프 cases 목록을 실행 한 후나는 다음과 같은 코드를 가지고

cases = [] 

for file in files: 

    # Get value from files and write to data 
    data = [ id, b, c, d, e, f, g, h, i, j, k ] 

    # Append the values to the data list 
    cases.append(data) 

# Sort the cases descending 
cases.sort(reverse=True) 

은 다음과 같습니다

cases = [ ['id', val, val], ['id', val, val], ['id', val, val] ] etc.

id 같은 값입니다 내림차순으로 정렬하려는 '600', '900', '1009', '1009a'또는 '1010'

'1009'가 목록 상단에있는 동안 '1009'와 '1010'사이에 있어야합니다. 이것은 아마도 '1009a'가 unicode으로 해석되고 다른 값은 long으로 구문 분석되는 것과 관련됩니다. 디버거에서도이를 확인합니다.

목록을 쓰는 동안 unicode(id)을 사용하여 유니 코드로 변환하려고 시도했지만 원하는 결과를 얻지 못했습니다. cases을 정렬하면 '600'에 도달 할 때까지 '999'부터 출력이 시작되고 '1130'에서 시작하여 '1000'까지 실행됩니다. '1130'에서 시작하여 '600'까지 실행하는 대신. 나는 '1009a'가 '1009'와 '1010'사이에있는 것을 원한다.

+0

id에는 가능한 값은 무엇입니까? 끝에 선택적 알파 자릿수가있는 숫자가 몇 개 있습니까? – Galen

+0

코드에서 구문 분석을 자르지 만, 코드를 변경하는 데 필요한 부분 인 것처럼 보입니다. 모호하게 묘사 된 부분 ('유니 코드 (id)'라고 말하고있는 곳)의 일부분을 보았지만 어떤 세부 묘사로도 표시하지 않았기 때문에 해결할 수는 없습니다. – Blckknght

답변

4

숫자가 포함 된 문자열을 비교하는 경우 알파벳순으로 정렬됩니다. 즉, 숫자에 몇 자리 숫자가 있는지에 관계없이 정렬됩니다. 먼저 int으로 변환해야하지만 a/b 접미사를 사용하면 문제가 발생합니다. 당신은 수와 접미사를 분리하는 정규 표현식을 사용할 수 있습니다

>>> p = re.compile(r"(\d+)(.*)") 
>>> def comp(x): 
...  n, s = p.match(x).groups() 
...  return int(n), s 
... 
>>> ids = ["1009", "1009a", "1009b", "1010", "99"] 
>>> [comp(x) for x in ids] 
[(1009, ''), (1009, 'a'), (1009, 'b'), (1010, ''), (99, '')] 
>>> sorted(ids, key=comp)     
['99', '1009', '1009a', '1009b', '1010'] 

귀하의 예제로이 적용을, 당신은 아마 (테스트하지)이 필요합니다

cases.sort(key=lambda x: comp(x[0]), reverse=True) 
+0

숫자 뒤에 문자가없는 경우에 'str'과 'NoneType'의 인스턴스 사이에 'TypeError :'< '가 지원되지 않습니다. comp 함수에서 'int int (n), s if else' ''로 변경하는 것이 좋습니다.또한, 아마도 어쩌면 향상되지 않을 수도 있습니다, 정규식은 글로벌 네임 스페이스의 혼란을 피하기 위해, comp 함수의 서명에 추가 될 수 있습니다.'def comp (x, p = re.compile (r "(\ d +) (. *) ")) :')) :' – Arne

+0

또한'comp '의 첫번째 줄을'n, s = p.match (x [0]). groups()'로 바꾸면 람다를 피하고'cases .sort (key = comp, reverse = True)' – Arne

+0

@ArneRecknagel이 Python 버전을 사용 했습니까? 나를 위해, 문자 부분은 ID가 문자가없는 경우 항상'''', '없음'이 아닌 경우에 항상입니다. Python 2.7 및 3.5로 테스트되었습니다. 'r "(\ d +) (. +)을 사용하면'None' 만됩니까?"' –

0

귀하의 문제는 당신이 때이다 unicode9>1이 있고 따라서 900>1000이 첫 번째 값과 비교됩니다. 당신이해야 할 일은

9000900이되고 지금보다 1000 수 있도록 모든 id 필드 앞에 0을 쓰기입니다. (그 일의 아마 깔끔한 방법이 있기는하지만) 당신은 코드의이 비트와 함께이 작업을 수행 할 수 있습니다 id 이미 문자열 인 경우는 str() 비트가 필요하지 않습니다

id = str(id).zfill(5) 

참고. 여기서 zfill(5)은 문자열의 길이가 0이 될 때까지 문자열 왼쪽에 0을 추가합니다.

+0

깔끔한 생각이지만, 이것은 "zfill"하고 "9090"을 "00090"이라고하고 "90b"를 "0090b"라고합니다. –

+0

네가 맞아. 또한이 함수는 실제로 더 이상 사용되지 않으며 Python 2.x에서만 작동하므로 아마도 최상의 옵션이 아닐 것이라고 읽습니다. 편집 : 그것은 여전히 ​​Python3.6에 남아 있으며 더 이상 사용되지 않는 것에 대해서는 아무 말도하지 않습니다. 하지만 아직까지는이 예제에서 작동하지 않습니다. –

0

@Tobias_k와 동일한 원칙이지만 깔끔하지는 않습니다.

from itertools import takewhile, dropwhile 

cases = [ ['600', 'foo1', 'bar1'], ['900', 'foo2', 'bar2'], ['1009', 'foo6', 'bar6'], ['1009a', 'foo3', 'bar3'], ['1010', 'foo4', 'bar4'] ] 

def sorter_helper(str_): 
    n = ''.join(takewhile(lambda x: x.isnumeric(), str_)) 
    s = ''.join(dropwhile(lambda x: x.isnumeric(), str_)) 
    return (int(n), s) 

cases = sorted(cases, key=lambda x: sorter_helper(x[0])) 
print(cases) # -> [['600', 'foo1', 'bar1'], ['900', 'foo2', 'bar2'], ['1009', 'foo6', 'bar6'], ['1009a', 'foo3', 'bar3'], ['1010', 'foo4', 'bar4']] 
관련 문제