Cadena perezosa.split -- # campo con strings campo con iterator campo con extension-methods campo con lazy camp codereview Relacionados El problema

Lazy String.Split


11
vote

problema

Español

C # S QuizCardPlayer1 El método proviene de C # 2.0, y las operaciones perezosas no eran una característica en ese momento. La tarea es dividir una cadena de acuerdo con un separador (único). Haciendo así con QuizCardPlayer2 se usa como

  QuizCardPlayer3  

Ahora, no es tan malo, pero si desea agregar más operaciones a ese QuizCardPlayer4 (y probablemente lo haga), deberá hacer unir en la matriz completa, básicamente iterando la cadena dos veces . Usando el comportamiento similar a la coroutina del perezoso QuizCardPlayer5 palabra clave, puede hacer más de una operación, mientras que solo está iterando una vez sobre la cadena.

  QuizCardPlayer6  

Si bien esto no tiene la opción "Eliminar entradas vacías", usando QuizCardPlayer7 ¿Debería realizar el trabajo con una operación 99887766655443328 , o estoy equivocado aquí?

No estoy seguro de la complejidad del tiempo usando co-rutinas, pero para la funcionalidad que he escrito algunas pruebas de unidad para asegurarse de que funcione:

  QuizCardPlayer9  
Original en ingles

C#'s String.Split method comes from C# 2.0, and lazy operations weren't a feature back then. The task is to split a string according to a (single) separator. Doing so with String.Split is used like

string[] split = myString.Split(new string[] { separator }); 

Now, not that bad, but if you want to add more operations to that string[] (and you probably do), you'll need to loop over the whole array, basically iterating the string twice. Using coroutine-like behaviour of the lazy yield keyword, you can (maybe) do more than one operation while only iterating once over the string.

public static IEnumerable<string> LazySplit(this string stringToSplit, string separator) {      if (stringToSplit == null) throw new ArgumentNullException("stringToSplit");     if (separator == null) throw new ArgumentNullException("separator");      var lastIndex = 0;     var index = -1;     do {         index = stringToSplit.IndexOf(separator, lastIndex);         if (index < 0 && lastIndex != stringToSplit.Length) {             yield return stringToSplit.Substring(lastIndex);             yield break;         } else if (index >= lastIndex) {             yield return stringToSplit.Substring(lastIndex, index - lastIndex);         }         lastIndex = index + separator.Length;     } while (index > 0); } 

While this does not have the "remove empty entries" option, using myString.LazySplit(separator).Where(str => !String.IsNullOrWhiteSpace(str)) should do the job with an O(n) operation, or am I wrong here?

I'm not sure about the time complexity using co-routines, but for the functionality I've written some unit tests to be sure its working:

[TestMethod] public void LazyStringSplit() {     var str = "ab;cd;;";     var resp = str.LazySplit(";");     var expected = new[] { "ab", "cd", "" };     var result = resp.ToArray();     CollectionAssert.AreEqual(expected, result); }  [TestMethod] public void LazyStringSplitEmptyString() {     var str = "";     var resp = str.LazySplit(";");     var expected = new string[0];     var result = resp.ToArray();     CollectionAssert.AreEqual(expected, result); }  [TestMethod] public void LazyStringSplitWithoutEmpty() {     var str = "ab;cd;;";     var resp = str.LazySplit(";").Where(s => !string.IsNullOrWhiteSpace(s));     var expected = new[] { "ab", "cd" };     var result = resp.ToArray();     CollectionAssert.AreEqual(expected, result); }  [TestMethod] public void LazyStringSplitNoSplit() {     var str = "ab;cd;;";     var resp = str.LazySplit(" ");     var expected = new[] { "ab;cd;;" };     var result = resp.ToArray();     CollectionAssert.AreEqual(expected, result); } 
              
       
       

Lista de respuestas

9
 
vote
vote
La mejor respuesta
 

Casos de borde:

  • ";abc".LazySplit(";") devolverá una secuencia vacía. Para que coincida El comportamiento de ";abc".Split(new char[] { ';' }) debe devolver la secuencia { "", "abc" } .

  • ";abc".LazySplit("") devolverá una secuencia con un solo elemento, el cuerda vacía. Para que coincida con el comportamiento de ";abc".Split(new char[] { }) debe devolver la secuencia { ";abc" } .

Así es como sugeriría escribirlo.

primero, trato con el separador vacío

  if (separator.Length == 0) {     yield return value;     yield break; }   

Luego, tenga dos variables, start end8 que se refieren al inicio y extremo de la subcadena que queremos extraer.

  var start = 0; for (var end = value.IndexOf(separator); end != -1; end = value.IndexOf(separator, start)) {     yield return value.Substring(start, end - start);     start = end + separator.Length; }  yield return value.Substring(start);   

Para hacer que sus pruebas de unidad coincidan con el comportamiento de ";abc".Split(new char[] { ';' })0 , también desea cambiar ";abc".Split(new char[] { ';' })1 para tener

  ";abc".Split(new char[] { ';' })2  

y ";abc".Split(new char[] { ';' })3 para tener

  ";abc".Split(new char[] { ';' })4  

Si desea probar que su implementación coincida con el comportamiento de ";abc".Split(new char[] { ';' })5 , sugeriría introducir un método de ayuda para las pruebas. Algo como

  ";abc".Split(new char[] { ';' })6  
 

Edge cases:

  • ";abc".LazySplit(";") will return an empty sequence. To match the behaviour of ";abc".Split(new char[] { ';' }) it should return the sequence { "", "abc" }.

  • ";abc".LazySplit("") will return a sequence with a single item, the empty string. To match the behaviour of ";abc".Split(new char[] { }) it should return the sequence { ";abc" }.

Here's how I would suggest writing it.

First, deal with the empty separator

if (separator.Length == 0) {     yield return value;     yield break; } 

Then have two variables, start and end that refer to the start and end of the substring we want to extract.

var start = 0; for (var end = value.IndexOf(separator); end != -1; end = value.IndexOf(separator, start)) {     yield return value.Substring(start, end - start);     start = end + separator.Length; }  yield return value.Substring(start); 

To make your unit tests match the behaviour of string.Split, you also want to change LazyStringSplit to have

var expected = new[] { "ab", "cd", "", "" }; 

and LazyStringSplitEmptyString to have

var expected = new string[] { "" }; 

If you want to test that your implementation matches the behaviour of string.Split, I would suggest introducing a helper method for the tests. Something like

var expected = value.Split(new string[] { separator }, StringSplitOptions.None); CollectionAssert.AreEqual(expected, value.LazySplit(separator)); 
 
 
 
 
2
 
vote

Necesitará hacer un bucle durante toda la matriz, básicamente iterando la cadena dos veces

Itherating dos veces no tiene que ser más lento que el iterativo una vez, si iterando una vez es más complicado. Cuando se trata de la complejidad del tiempo, ambas opciones son $ O (N) $. Cuando se trata del rendimiento real, necesita medir . (Y eso es asumiendo que el desempeño de este código en realidad importa.)

Específicamente, las matrices son muy eficientes en .NET, mientras que iterando ";abc".Split(new char[] { ';' })7 requiere dos llamadas virtuales para cada elemento.

 

you'll need to loop over the whole array, basically iterating the string twice

Iterating twice doesn't have to be slower than iterating once, if iterating once is more complicated. When it comes to time complexity, both options are \$O(n)\$. When it comes to actual performance, you need to measure. (And that's assuming that performance of this code actually matters.)

Specifically, arrays are very efficient in .Net, whereas iterating IEnumerable requires two virtual calls for every item.

 
 

Relacionados problema

4  Plegable de terminación temprana para flujos de Scala  ( Early termination foldleft for scala streams ) 
El Observer9 #ifndef OBSERVER_H_INCLUDED #define OBSERVER_H_INCLUDED #include <string> class Publisher; class Observer { public: virtual void eventOn...

3  ¿Hay algún problema en esta implementación "perezosa"?  ( Are there any issues in this lazy implementation ) 
He escrito después de la pequeña utilidad para abstraer la lógica de inicialización perezosa. (Tiendo a usar variables perezosas con bastante frecuencia.) ¿...

3  Caché Azure GetLeradd (sin bloqueo)  ( Azure cache getoradd without locking ) 
inspirado en la implementación no bloqueada propuesta en esta publicación , el siguiente código es un intento de (acerca de) hacer lo mismo utilizando el ca...

3  Determinar de manera eficiente todos los factores de un número natural dado  ( Efficiently determine every factor of a given natural number ) 
No es difícil encontrar todos los factores de un número natural dado. A continuación se muestra una función bastante rápida de Python que puede hacer solo: (...

3  Protocolo Swift con requisito de propiedad perezosa  ( Swift protocol with lazy property requirement ) 
Primera pregunta aquí en CodereView. Fui dirigido aquí desde una pregunta. Pregunté así: Protocolo SWIFT con propiedades perezosas: no se puede usar Mutating...

3  Aplanar un árbol a una colección de nodos  ( Flatten a tree to a collection of nodes ) 
He implementado una clase de árbol simple de la siguiente manera: '/uploads'5 Esto funciona, pero tengo preocupaciones sobre la siguiente línea: '/up...

7  Clase de valor almacenado en caché genérico imitando perezosos <t>  ( Generic cached value class mimicking lazyt ) 
Antes de escribir esto, busqué y encontré una serie de soluciones que hacen uso de un proveedor de almacenamiento en caché para manejar un conjunto de artícul...

12  Resetablelazy <t>: una versión reiniciable de .NET Lazy <t>  ( Resettablelazyt a resettable version of net lazyt ) 
Implementé una versión reiniciable de .NET Lazy (contexto: en su mayoría para usarlo en una memoria de memoria para obtener fines de actualización automática ...

16  Lectura perezosa de la propiedad cargada  ( Lazy loaded property readability ) 
Actualmente tengo código que se parece a esto checkOnline.sh2 Resharper está sugiriendo que cambie la propiedad a: checkOnline.sh3 Esto no es un i...

5  Singletons con instanciación ansiosa y perezosa  ( Singletons with eager and lazy instantiation ) 
He encontrado más de una implementación del patrón de Singleton en Java (más como 5-6). Quiero saber si los dos siguientes fragmentos de código (escrito por M...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos