Arrays en VB.net

Iniciado por xRayderx, 6 Marzo 2018, 04:48 AM

0 Miembros y 1 Visitante están viendo este tema.

xRayderx

Hola, soy nuevo en el tema de arrays en vb.net y tengo una duda acerca de como codificar lo siguiente:

quiero realizar un programa que mediante cajas de texto almacene en 2 arrays 20 numeros, luego sumar los elementos de cada arreglo, ubicarlos de mayor a menor y que el promedio de los datos se almacene en otro arreglo mostrando los resultados en un listbox.

Saludos!

Eleкtro

#1
Hola. Ha quedado claro lo que quieres hacer, ¿pero podrías explicar exactamente con que cosa es que estás teniendo dificultades para avanzar?, empecemos por lo básico: ¿sabes declarar y usar un array, o una colección enumerable?.




Bueno, te explicaré un poco por encima como puedes llevarlo todo a cabo:

1. asumiremos que en realidad no tienes ninguna necesidad real de utilizar un Array, por ende, declara una colección genérica, de tipo List(Of Integer) (por ejemplo).

2. si estás usando un botón para añadir el valor especificado en el TextBox, entonces suscríbete al evento Button.Click y ahí añades un elemento (el texto del TextBox) a la colección List que declaraste.
si no usas un botón, como alternativa puedes suscribirte al evento TextBox.KeyPress para interceptar la tecla "ENTER" y añadir el elemento a la colección.

3. sumar todos los elementos de una colección es tan simple como utilizar LINQ, concretamente la extensión de método IEnumerable(Of Integer).Sum()

Ejemplo:

Código (vbnet) [Seleccionar]
Dim list As New List(Of Integer)
list.AddRange({1, 1})

Dim sum As Integer = list.Sum()
Debug.WriteLine(sum)


5. Para ordenar los elementos, más de lo mismo, puedes usar LINQ:

Código (vbnet) [Seleccionar]
Dim list As New List(Of Integer)
list.AddRange({8, 2, 1})

Dim sortedSecuence As IEnumerable(Of Integer) =
   From i As Integer In list
   Order By i Ascending

Debug.WriteLine(String.Join(", ", sortedSecuence))


...o bien el método List.Sort() si quieres aplicar los cambios diréctamente en el objeto:

Código (vbnet) [Seleccionar]
Dim list As New List(Of Integer)
list.AddRange({8, 2, 1})

list.Sort(Comparer(Of Integer).Default)
Debug.WriteLine(String.Join(", ", list))


...o bien en lugar de usar una colección de tipo List como hemos mostrado hasta ahora, en su lugar puedes usar una colección de tipo SortedSet ,
esto sería lo más conveniente suponiendo que siempre quieras mantener ordenados los elementos en la colección:

Código (vbnet) [Seleccionar]
Dim sortedset As New SortedSet(Of Integer)(Comparer(Of Integer).Default)
sortedset.Add(8)
sortedset.Add(2)
sortedset.Add(1)

Debug.WriteLine(String.Join(", ", sortedset))


6. Para introducir/representar los datos en el ListBox, si estás usando una colección de tipo List simplemente tienes que hacer:

Código (vbnet) [Seleccionar]
Me.ListBox1.DataSource = lista

Si por lo contrario usas una colección de tipo SortedSet, primero tienes que convertir el tipo de colección a IList, de la siguiente manera:

Código (vbnet) [Seleccionar]
Me.ListBox1.DataSource = sortedset.ToList()

Nota: en lugar de la propiedad ListBox.DataSource puedes utilizar los métodos ListBox.Items.Add() y ListBox.Items.AddRange() para añadir los elementos, pero lo veo innecesario dado el caso.

EDITO: acabo de fijarme mejor en tu pregunta y veo que quieres ordenar los números de mayor a menor, ok entonces en el ejemplo de LINQ solo deberías modificar el keyword "Ascending" por "Descending", en los otros ejemplos de ordenamiento podrías usar el método de extensión de LINQ: IEnumerable(Of Integer).Reverse ( List.Reverse() o SortedSet.Reverse() ) o también puedes declarar una clase e implementar la interfaz IComparer(Of Integer) y pasársela como parámetro al constructor de la clase SortedSet para mantener de forma automática una ordenación de mayor a menor.

Saludos!








xRayderx

Cita de: Eleкtro en  6 Marzo 2018, 06:03 AM
Hola. Ha quedado claro lo que quieres hacer, ¿pero podrías explicar exactamente con que cosa es que estás teniendo dificultades para avanzar?, empecemos por lo básico: ¿sabes declarar y usar un array, o una colección enumerable?.




Bueno, te explicaré un poco por encima como puedes llevarlo todo a cabo:

1. asumiremos que en realidad no tienes ninguna necesidad real de utilizar un Array, por ende, declara una colección genérica, de tipo List(Of Integer) (por ejemplo).

2. si estás usando un botón para añadir el valor especificado en el TextBox, entonces suscríbete al evento Button.Click y ahí añades un elemento (el texto del TextBox) a la colección List que declaraste.
si no usas un botón, como alternativa puedes suscribirte al evento TextBox.KeyPress para interceptar la tecla "ENTER" y añadir el elemento a la colección.

3. sumar todos los elementos de una colección es tan simple como utilizar LINQ, concretamente la extensión de método IEnumerable(Of Integer).Sum()

Ejemplo:

Código (vbnet) [Seleccionar]
Dim list As New List(Of Integer)
list.AddRange({1, 1})

Dim sum As Integer = list.Sum()
Debug.WriteLine(sum)


5. Para ordenar los elementos, más de lo mismo, puedes usar LINQ:

Código (vbnet) [Seleccionar]
Dim list As New List(Of Integer)
list.AddRange({8, 2, 1})

Dim sortedSecuence As IEnumerable(Of Integer) =
   From i As Integer In list
   Order By i Ascending

Debug.WriteLine(String.Join(", ", sortedSecuence))


...o bien el método List.Sort() si quieres aplicar los cambios diréctamente en el objeto:

Código (vbnet) [Seleccionar]
Dim list As New List(Of Integer)
list.AddRange({8, 2, 1})

list.Sort(Comparer(Of Integer).Default)
Debug.WriteLine(String.Join(", ", list))


...o bien en lugar de usar una colección de tipo List como hemos mostrado hasta ahora, en su lugar puedes usar una colección de tipo SortedSet ,
esto sería lo más conveniente suponiendo que siempre quieras mantener ordenados los elementos en la colección:

Código (vbnet) [Seleccionar]
Dim sortedset As New SortedSet(Of Integer)(Comparer(Of Integer).Default)
sortedset.Add(8)
sortedset.Add(2)
sortedset.Add(1)

Debug.WriteLine(String.Join(", ", sortedset))


6. Para introducir/representar los datos en el ListBox, si estás usando una colección de tipo List simplemente tienes que hacer:

Código (vbnet) [Seleccionar]
Me.ListBox1.DataSource = lista

Si por lo contrario usas una colección de tipo SortedSet, primero tienes que convertir el tipo de colección a IList, de la siguiente manera:

Código (vbnet) [Seleccionar]
Me.ListBox1.DataSource = sortedset.ToList()

Nota: en lugar de la propiedad ListBox.DataSource puedes utilizar los métodos ListBox.Items.Add() y ListBox.Items.AddRange() para añadir los elementos, pero lo veo innecesario dado el caso.

EDITO: acabo de fijarme mejor en tu pregunta y veo que quieres ordenar los números de mayor a menor, ok entonces en el ejemplo de LINQ solo deberías modificar el keyword "Ascending" por "Descending", en los otros ejemplos de ordenamiento podrías usar el método de extensión de LINQ: IEnumerable(Of Integer).Reverse ( List.Reverse() o SortedSet.Reverse() ) o también puedes declarar una clase e implementar la interfaz IComparer(Of Integer) y pasársela como parámetro al constructor de la clase SortedSet para mantener de forma automática una ordenación de mayor a menor.

Saludos!

Hola, si se declarar un array, pero como mencione , apenas me estoy inicializando en la codificacion del mismo y la verdad mas de ahi poco y nada. Estoy realizando un informe sobre arrays para mi clase de programacion y me asignaron un ejercicio el cual he mencionado en el post.

Bien, lo que he estado pensando es en agregar mediante un textbox 20 numeros, los cuales quiero sumar con la ayuda de un boton. A continuacion, una vez sumados se ordenen de mayor a menor y en otro arreglo calcule el promedio y se muestre en un listbox.

A todo esto, olvide mencionar que este problema debe contener una validacion de datos.

Muchas gracias por responder!

Serapis

#3
La respuesta que te ha dado Elektro es muy válida, pero para programadores con algo más de soltura. ciertamente si estás empezando y a duras penas sabes que es un array y otras estructuras, necesitarías más tiempo (posiblemente) del que dispones para ser capaz de entender y aplicar satisfactoriamente lo que te explica.

A tu nivel...

Declara un array de 20 elementos, un valor para contener el valor actual y un índice que refleje cuantos llevas ya acumulados en tu array...
Código (vbnet) [Seleccionar]

   Dim miArray(0 To 19) As Object  ' por ejemplo, o un tipo numérico que prefieras... si luego quieres añadir elementos uno a uno.
   Dim miMumero As Int32
   Dim miIndice As Byte


Se supone que al menos tienes en la interfaz un textbox, un botón y un listbox...
Entonces deberías usar el evento Validate del textbox...
Código (vbnet) [Seleccionar]

Private Sub TextBox1_Validating(... , ByVal e As CancelEventArgs) Handles textBox1.Validating
       Try
           miMumero = Integer.Parse(TextBox1.Text)
           TextBox1.Clear()  ' es lo mismo que Textbox1.Text = ""            
           e.Cancel = False
       Catch
           e.Cancel = True
           MessageBox.Show("El texto no puede ser interpretado como un número (o número entero), o bien excede el valor de un int32....", "Error...")
           ' puedes seleccionar el texto del control, o borrarlo... en cualquier caso el foco regresa al control textbox, para editar su contenido...
       End Try
   End Sub


Cuando escribes el texto del número en el textbox, ese control tiene el foco, luego cuando otro control intenta ganar el foco (por ejemplo cuando pulsas el botón), se genera el evento Validating del textbox, si no valida, el foco se mantiene en el textbox... (forzándolo con Cancel=True) pero si valida, se genera el evento Validated...
Fíjate que ni siquiera colocamos código en el botón... aunque puede hacerse así, por supuesto.


Código (vbnet) [Seleccionar]

Private Sub TextBox1_Validated(sender..., e As EventArgs) Handles TextBox1.Validated
       miArray(miIndice) = miMumero
       miIndice += 1
       If (miIndice < 20) Then
           MessageBox.Show("Número almacenado, introduzca el siguiente número...")
           TextBox1.Focus()
       Else
           TextBox1.Enabled = False
           Button1.Enabled = False

           Call Calcular()  ' ahora que tenemos el array completo, podemos hacer el resto de cosas.
       End if
end Sub


Te diría que crearas un algoritmo de ordenación si tuvieras más conocimientos.
Aparte el Listbox tiene una propiedad Sorted, que se activa en diseño y así cuando se añada un ítem se ordena automáticamente.... pero hay un problema, y es que (si no recuerdo mal de memoria), solo ordena de menor a mayor, y tu lo precisas al revés...

...pero en realidad es más fácil... los arrays tienen un método sort...
Código (vbnet) [Seleccionar]

Private Sub Calcular()
       miArray(0) = 12
       miArray(15) = 87
       Array.Sort(miArray, 0, 20) ' No son precisos los 2 parámetros, si no se indican se ordena todo el array, pero los pongo, para que te des cuenta, que puedes ordenarlo parcialmente si fuera preciso.
       Array.Reverse(miArray) ' invertimos el orden, o bien mediante un bucle añadir elementos al listbos, uno a uno, empezando por el final del array...
       ListBox1.Items.AddRange(miArray) ' Si declaraste el array de tipo numérico, usa un bucle con el método Add (por ejemplo).

       ' Suma
       Dim suma As Int32

       For k As Byte = 0 To 19
           suma += miArray(k)
       Next
       MessageBox.Show("La suma total del array es: " & suma.ToString)

       ' Media, mediana, moda ???
       Dim media As Single = (suma \ 20)
       MessageBox.Show("La media de los valores del array es: " & media.ToString)
   End Sub


...y bueno la validación que indicas, no sé a que te refieres, no sé qué tienes que validar, yo he validado si el texto introducido puede ser tomado como un numero entero de 32bits (ni siquiera un decimal), y lo que falte o haya quedado claro, o haya entendido mal, espero que sepas arreglarlo... tienes suficiente para resol bverlo con poco esfuerzo de tu parte.

xRayderx

Cita de: NEBIRE en  7 Marzo 2018, 05:51 AM
La respuesta que te ha dado Elektro es muy válida, pero para programadores con algo más de soltura. ciertamente si estás empezando y a duras penas sabes que es un array y otras estructuras, necesitarías más tiempo (posiblemente) del que dispones para ser capaz de entender y aplicar satisfactoriamente lo que te explica.

A tu nivel...

Declara un array de 20 elementos, un valor para contener el valor actual y un índice que refleje cuantos llevas ya acumulados en tu array...
Código (vbnet) [Seleccionar]

   Dim miArray(0 To 19) As Object  ' por ejemplo, o un tipo numérico que prefieras... si luego quieres añadir elementos uno a uno.
   Dim miMumero As Int32
   Dim miIndice As Byte


Se supone que al menos tienes en la interfaz un textbox, un botón y un listbox...
Entonces deberías usar el evento Validate del textbox...
Código (vbnet) [Seleccionar]

Private Sub TextBox1_Validating(... , ByVal e As CancelEventArgs) Handles textBox1.Validating
       Try
           miMumero = Integer.Parse(TextBox1.Text)
           TextBox1.Clear()  ' es lo mismo que Textbox1.Text = ""            
           e.Cancel = False
       Catch
           e.Cancel = True
           MessageBox.Show("El texto no puede ser interpretado como un número (o número entero), o bien excede el valor de un int32....", "Error...")
           ' puedes seleccionar el texto del control, o borrarlo... en cualquier caso el foco regresa al control textbox, para editar su contenido...
       End Try
   End Sub


Cuando escribes el texto del número en el textbox, ese control tiene el foco, luego cuando otro control intenta ganar el foco (por ejemplo cuando pulsas el botón), se genera el evento Validating del textbox, si no valida, el foco se mantiene en el textbox... (forzándolo con Cancel=True) pero si valida, se genera el evento Validated...
Fíjate que ni siquiera colocamos código en el botón... aunque puede hacerse así, por supuesto.


Código (vbnet) [Seleccionar]

Private Sub TextBox1_Validated(sender..., e As EventArgs) Handles TextBox1.Validated
       miArray(miIndice) = miMumero
       miIndice += 1
       If (miIndice < 20) Then
           MessageBox.Show("Número almacenado, introduzca el siguiente número...")
           TextBox1.Focus()
       Else
           TextBox1.Enabled = False
           Button1.Enabled = False

           Call Calcular()  ' ahora que tenemos el array completo, podemos hacer el resto de cosas.
       End if
end Sub


Te diría que crearas un algoritmo de ordenación si tuvieras más conocimientos.
Aparte el Listbox tiene una propiedad Sorted, que se activa en diseño y así cuando se añada un ítem se ordena automáticamente.... pero hay un problema, y es que (si no recuerdo mal de memoria), solo ordena de menor a mayor, y tu lo precisas al revés...

...pero en realidad es más fácil... los arrays tienen un método sort...
Código (vbnet) [Seleccionar]

Private Sub Calcular()
       miArray(0) = 12
       miArray(15) = 87
       Array.Sort(miArray, 0, 20) ' No son precisos los 2 parámetros, si no se indican se ordena todo el array, pero los pongo, para que te des cuenta, que puedes ordenarlo parcialmente si fuera preciso.
       Array.Reverse(miArray) ' invertimos el orden, o bien mediante un bucle añadir elementos al listbos, uno a uno, empezando por el final del array...
       ListBox1.Items.AddRange(miArray) ' Si declaraste el array de tipo numérico, usa un bucle con el método Add (por ejemplo).

       ' Suma
       Dim suma As Int32

       For k As Byte = 0 To 19
           suma += miArray(k)
       Next
       MessageBox.Show("La suma total del array es: " & suma.ToString)

       ' Media, mediana, moda ???
       Dim media As Single = (suma \ 20)
       MessageBox.Show("La media de los valores del array es: " & media.ToString)
   End Sub


...y bueno la validación que indicas, no sé a que te refieres, no sé qué tienes que validar, yo he validado si el texto introducido puede ser tomado como un numero entero de 32bits (ni siquiera un decimal), y lo que falte o haya quedado claro, o haya entendido mal, espero que sepas arreglarlo... tienes suficiente para resol bverlo con poco esfuerzo de tu parte.


Hola, estuve siguiendo estos pasos que me comentaste y lo codifique de la siguiente manera:


    Dim miMumero As Integer
    Dim miIndice As Byte
    Dim miArray(0 To 19) As Object
    Private Sub TextBox1_Validated(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.Validated
        miArray(miIndice) = miMumero
        miIndice += 1
        If (miIndice < 20) Then
            MessageBox.Show("Número almacenado, introduzca el siguiente número...")
            TextBox1.Focus()
        Else
            TextBox1.Enabled = False
            btnCalcular.Enabled = False

            Call Calcular() 

        End If

    End Sub

    Private Sub calcular()
        miArray(0) = 12
        miArray(15) = 87
        ListBox1.Items.AddRange(miArray)

        ' Suma
        Dim suma As Int32

        For k As Byte = 0 To 19
            suma += miArray(k)
        Next
        MessageBox.Show("La suma total del array es: " & suma.ToString)

       
        Dim media As Single = (suma \ 20)
        MessageBox.Show("La media de los valores del array es: " & media.ToString)
    End Sub


En el diseño del formulario coloque 1 textbox, 1 boton y 1 listbox. Bien, ya agregados los numeros mediante listbox, este hace la suma y calcula el promedio, pero al mostrarlo en el listbox aparecen varios 0 y otros numeros al parecer aleatorios.

Serapis

Cita de: xRayderx en  8 Marzo 2018, 05:14 AM
Hola, estuve siguiendo estos pasos que me comentaste y lo codifique de la siguiente manera:

    Private Sub calcular()
        miArray(0) = 12
        miArray(15) = 87
        ListBox1.Items.AddRange(miArray)
        ...
        ...
        ...
    End Sub

En el diseño del formulario coloque 1 textbox, 1 boton y 1 listbox. Bien, ya agregados los numeros mediante listbox, este hace la suma y calcula el promedio,

pero al mostrarlo en el listbox aparecen varios 0 y otros numeros al parecer aleatorios.
Claro... si lees bien el código en la función calcular, sobran las 2 primeras líneas... yo las puse de ejemplo:
miArray(0) = 12
miArray(15) = 87
Solución: borra esas dos líneas (siempre lee el código y trata de entenderlo, para que no pase eso, copiar y pegar sin más no está bien).

En cuanto a los valores, 0 y otros... te has comido el código del evento 'Validating'... luego no existe ninguna validación, el evento 'validated', se lleva a cabo en ausencia de su correspondiente 'validating'...
Solución: Incluye el código del evento Validating