Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversaHola programadores de JSL,
Tuve un pequeño problema como parte de una aplicación más grande y pensé en compartirlo con ustedes y ver si hay una manera de hacerlo mejor o más inteligente.
Básicamente tengo un vector de 1 y 0 (es decir, [1, 1, 0, 0, 1]) que necesito convertir en una cadena de Y y N (es decir, "YYNNY").Luego necesito hacer lo contrario, es decir, convertir una cadena de Y y N nuevamente en un vector de 1 y 0.
Aquí están mis funciones rápidas y sucias: ¡veamos si se te ocurre algo más allá de mi débil capacidad intelectual!
// Convert a vector of 1s and 0s to a string with no separators
matrix_10_to_yn = function({matrix_10}, {default local},
yn_txt = "";
if (nrows(matrix_10) > 0,
// Strip out square brackets and commas
yn_txt = substitute(char(matrix_10), "[", "", "]", "", ", ", "");
// Now convert 1s to Y and 0s to N
yn_txt = substitute(yn_txt, "1", "Y", "0", "N");
);
yn_txt;
);
// Convert a YN string with no separators to a vector of 1s and 0s
yn_to_matrix_10 = function({yn_txt}, {default local},
n = length(yn_txt);
matrix_10 = j(n, 1, 0);
for (i = 1, i <= n, i++,
if (substr(yn_txt, i, 1) == "Y",
matrix_10[i] = 1;
);
);
matrix_10;
);
<BR />// Test thing out
a = yn_to_matrix_10("YYYNNNN"); show(a);
b = matrix_10_to_yn(a); show(b);
c = yn_to_matrix_10(""); show(c);
d = matrix_10_to_yn(c); show(d);Re: Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversaSoluciones tan geniales.No puedo creer la variedad de enfoques utilizados para resolver este problema relativamente simple.Gracias de nuevo a todos.
Re: Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversaTodas estas son soluciones geniales. PMROZ señaló que entendí mal que el secanrio debe comenzar con una lista. Me pidió mi solución revisada.A continuación se convierte una lista o una cadena de YN en un vector de decenas y un vector de decenas en una cadena de YN.
Para ser coherente con mi publicación anterior, simplemente convertí la cadena en una lista con la función palabras() usando un delimitador de cadena vacío.
exmat = J(25,1, RandomInteger(0,1));
exlst = Insert({}, {"Y", "N"}[2-exmat]);
exstr = ConcatItems(Insert({}, {"Y", "N"}[2-exmat]), "");
convert_yn = Function({usr}, {rslt=empty(), ynList ={"Y","N"} },
if(IsMatrix(usr),
rslt = ConcatItems(insert({},ynList[2-usr]),"")
, //else
IsList(usr),
rslt = J(nitems(usr),1, 1);
rslt[loc(usr,"N")]=0
, //else
IsString(usr),
rslt = J(length(Trim(usr)),1,1);
rslt[loc(words(usr,""),"N")]=0
); //end if
rslt
); //end Function
show(exmat, convert_yn(exmat), exlst, convert_yn(exlst), exstr, convert_yn(exstr) );Re: Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversaUtilizo una función genérica 'mapply' en la mayoría de los proyectos, por lo que normalmente solo necesitaría las dos últimas líneas:
Names Default to here(1);
// Utility function to make for loops, combo 'map' and 'apply'
// this is a 'fake' map/apply function because it allows side
// effects (like apply) and it also returns a value (like map)
mapply = function( {x, foo, arg1 = "__missing", arg2 = "__missing"}, { i, r = {}, x, foo, arg1, arg2, arg1missing, arg2missing },
if( N Items( x ) < 1,
return({}), //empty list supplied, return an empty list
for( i = 1, i <= N Items(x), i++,
arg1missing = 0; arg2missing = 0;
If( type(arg1) == "String", If( arg1 == "__missing", arg1missing = 1 ) );
If( type(arg2) == "String", If( arg2 == "__missing", arg2missing = 1 ) );
if(
arg1missing == 1,
r = Insert( r, foo( x[i] ) ),
arg2missing == 1,
r = Insert( r, foo( x[i], arg1 ) ),
r = Insert( r, foo( x[i], arg1, arg2 ) )
)
)
);
return(r);
);
// Solution:
str = "YYYNNNNYYNY";
(numbers = mapply( words(str,""), function( {x}, if( x=="Y", 1, 0) ) ) )
mapply( as list(numbers), function( {x}, if( x==1,"Y", "N") ) )Re: Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversa@pmroz ,
Aquí está mi opinión/intento de esto. Gracias por ofrecer este interesante desafío. Sé que estoy usando un bucle que no sé si se escalará bien en matrices grandes, pero pensé que a otros en la comunidad se les puede ocurrir una manera más rápida.
Clear Log(); Clear Globals();
ex = Associative Array({1,0} ,{"Y", "N"});
Test = [1,0, 1, 1, 1, 0, 0, 1, 0, 1];
Res = {};
for(i = 1, i <= N Rows(Test), i++,
Insert Into(Res, ex << Get Value(Test[i]));
);
Show(Res);
Re: Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversa¡Y ahora necesito estudiar la función design()!
Re: Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversaVaya, estos son increíbles.¡Gracias a todos!
Re: Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversaVaya, no vi la respuesta de Craig... creo que su versión es mejor.
Re: Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversapuede realizar la conversión de cadena a matriz en una sola línea usando Char to Blob y Blob to Matrix. Mi contribución:
names default to here(1);
a=[1,0, 1, 1, 1, 0, 0, 1, 0, 1];
b="YNYYYNNYNY";
f_YNString_to_IndicatorVector=Function({s},
blob to matrix(char to blob(d),"int", 1, "little", 1)==89;
);
f_IndicatorVector_to_YNString=Function({v},{vv},
vv=As List(v);
vv[loc(v)]="Y";
vv[loc(!v)]="N";
concat items(vv,"");
);
show(a);
show(b);
Show(f_YNString_to_IndicatorVector(b));
Show(f_IndicatorVector_to_YNString(a));
Show(f_IndicatorVector_to_YNString(f_YNString_to_IndicatorVector(b)));
Re: Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversa
Esto no se extenderá a tres valores o valores faltantes/errores sin un esfuerzo adicional. Convierte cadena--blob--matriz y realiza la detección Y y N utilizando el número del carácter ASCII en la matriz. Se indica a las funciones BlobToMatrix y MatrixToBlob que utilicen enteros little-endian de 1 byte. El endianismo no es crítico para números de 1 byte, el tamaño grande funciona igual de bien. Depende de que los caracteres tengan representaciones de un byte.
source = "YYNNYQ";
// if you are uncomfortable with hard coded constants...
Yvalue = Blob To Matrix( Char To Blob( "Y" ), "int", 1, "little" )[1]; // 89
Nvalue = Blob To Matrix( Char To Blob( "N" ), "int", 1, "little" )[1]; // 78
// forward
numbers = Blob To Matrix( Char To Blob( source ), "int", 1, "little" ) == Yvalue;
// reverse
string = Blob To Char( Matrix To Blob( Nvalue + numbers * (Yvalue - Nvalue), "int", 1, "little" ) );
// display
Show( source, numbers, string );
fuente = "YYNNYQ";
números = [1, 1, 0, 0, 1, 0];
cadena = "YYNNYN";
Re: Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversa¡¡Otro!!
Names Default to here(1);
yto1 = function({str},
{DEFAULT LOCAL},
list = words(str, "");
design(list, {"Y"});
);
oneToY = function({mat},
list = substitute(as list(mat), 1, "Y", 0, "N");
Concat items(list, "");
);
str = "YYYNNNNYYNY";
nums = yto1(str);
show(nums);
str2 = oneToY(nums);
show(str2, str2==str);Re: Desafío de programación JSL: convertir de una cadena de Y y N a una matriz de 1 y 0, y viceversa¡Lo que funcione, funciona!Aquí hay una alternativa.
exmat = J(25,1, RandomInteger(0,1));
exlst = Insert({}, {"Y", "N"}[2-exmat]);
convert_yn = Function({usr}, {rslt, ynList ={"Y","N"} },
if(IsMatrix(usr),
rslt = insert({},ynList[2-usr])
, //else
rslt = J(nitems(usr),1, 1);
rslt[loc(usr,"N")]=0
); //end if
rslt
); //end Function
show(exmat, convert_yn(exmat), exlst, convert_yn(exlst));