1+ import unicodedata
12from abc import ABC , abstractmethod
23from bisect import bisect_left
34from itertools import islice
@@ -178,11 +179,20 @@ def create_value_safe_set(self, values: pd.Series) -> None:
178179class StringConvertor (DataConvertor ):
179180 def __init__ (self , values : Iterable [Value ]) -> None :
180181 super ().__init__ ()
181- unique_values = set (v for v in values if not pd .isna (v ))
182- for value in unique_values :
183- if not isinstance (value , str ):
184- raise TypeError (f"Not a `str` object in a string dtype column: { value } ." )
185- self .value_map = sorted (cast (Set [str ], unique_values ))
182+ unique_values = set ()
183+ for v in values :
184+ if not pd .isna (v ):
185+ if not isinstance (v , str ):
186+ raise TypeError (f"Not a `str` object in a string dtype column: { v } ." )
187+
188+ # Normalize to NFC form to handle composed vs decomposed Unicode consistently
189+ # This ensures "café" and "cafe\u0301" are treated as the same string
190+ normalized_value = unicodedata .normalize ("NFC" , v )
191+ unique_values .add (normalized_value )
192+
193+ # Use locale-independent binary sorting for consistent results across systems
194+ # This ensures the same ordering regardless of system locale settings
195+ self .value_map = sorted (unique_values , key = lambda x : x .encode ("utf-8" ))
186196
187197 # Note that self.safe_values is only used if self.value_safe_flag is False
188198 self .safe_values : Set [float ] = set ()
@@ -197,7 +207,9 @@ def column_type(self) -> ColumnType:
197207
198208 def to_float (self , value : Value ) -> float :
199209 # Note that value here is the string itself, not an index.
200- index = bisect_left (self .value_map , cast (str , value ))
210+ # Normalize the lookup value the same way we normalized during initialization
211+ normalized_value = unicodedata .normalize ("NFC" , cast (str , value ))
212+ index = bisect_left (self .value_map , normalized_value )
201213 assert index >= 0 and index < len (self .value_map )
202214 return float (index )
203215
0 commit comments