How to Split a List Proportionately 32%, 32% and 36%

Asked

Viewed 203 times

0

I own a lista("arquivo txt") with about 150 values with three types of flowers "Iris-setosa", "Iris-versicolor", "Iris-virginica" I need to read this file, check the amount of each flower in that file, and after knowing the exact amount generate 3 new lists divided proportionally by the amount of each flower in the file.

file example:

5.7,2.8,4.1,1.3,Iris-versicolor

6.3,3.3,6.0,2.5,Iris-virginica

5.1,3.5,1.4,0.2,Iris-setosa

read the file I have already managed, the problem is to see how many have of each and divide in 3 new list proportionally by the amount of each flower.

let’s say you have 50 of each flower, I need to put about 17 flowers of each type in a new list.

could help me ?

What I have so far

namespace Classificadores
{
   class Program
   {       
    static void Main(string[] args)
    {
        List<Flor> flores = Flor.GetFlores();

        var rnd = new Random();
        var query =
        from i in flores
        let r = rnd.Next()
        orderby r
        select i;

        var shuffledFlores = query.ToList();

        List<Flor> ShuffleFlores1 = new List<Flor>();
        List<Flor> ShuffleFlores2 = new List<Flor>();
        List<Flor> ShuffleFlores3 = new List<Flor>();

        for(int i = 0; i < shuffledFlores.Count; i++)
        {

        }         

        double[] flor = { 6.1, 2.8, 4.7, 1.2 };      

        Console.WriteLine(Flor.Classifier(ShuffleFlores1, flor));

        Console.ReadLine();
    }
}
}

public class Flor
{
    public double[] Features;
    public string Nome { get; set; }
    public Flor(double sepalLenght, double sepalWidth, double petalLenght, double petalWidth, string Nome)
    {
        Features = new double[4];
        Features[0] = sepalLenght;
        Features[1] = sepalWidth;
        Features[2] = petalLenght;
        Features[3] = petalWidth;
        this.Nome = Nome;
    }

    public static double Distance(double[] a, double[] b)
    {
        double sum = 0;
        for (int i = 0; i < a.Length; i++)
            sum += Math.Pow(a[i] - b[i], 2);
        return Math.Sqrt(sum);
    }

    public static string Classifier(List<Flor> flores, double[] Features)
    {
        double val = 0.0;
        double min = double.MaxValue;
        string label = String.Empty;
        foreach (Flor flor in flores)
        {
            val = Distance(flor.Features, Features);
            if (val < min)
            {
                min = val;
                label = flor.Nome;
            }
        }
        return label;
    }

    public static List<Flor> GetFlores()
    {
        List<Flor> flores = new List<Flor>();
        var colunas = File.ReadAllLines(@"C:\Flor.txt");

        foreach (string coluna in colunas)
        {
            var linha = coluna.Split(",");
            var flor = new Flor(Convert.ToDouble(linha[0]), Convert.ToDouble(linha[1]), Convert.ToDouble(linha[2]), Convert.ToDouble(linha[3]), linha[4]);
            flores.Add(flor);
        }

        return flores;
    }
}
  • 2

    To count each type of flower you can use Count (LINQ): int setosa = flores.Count(f => f.Nome == "Iris-setosa"); as for the rest has become difficult to understand exactly what you want to do...

  • if you have a List<Flor> with 150 elements, which have 3 types of flower, for example, 50 flowers of each type, and want to divide each type into 3 equal parts, so you want to stay with 9 lists? that’s it?

  • @Vik actually I need 3 proportional lists, I need 33% of each flower in each list

2 answers

1


See if this is it:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace ConsoleApp14
{
    class Program
    {
        static void Main(string[] args)
        {
            var flores = GetDummyFlores();

            List<Flor> ShuffleFlores1 = new List<Flor>();
            List<Flor> ShuffleFlores2 = new List<Flor>();
            List<Flor> ShuffleFlores3 = new List<Flor>();

            var allLists = new List<List<Flor>>() { ShuffleFlores1, ShuffleFlores2, ShuffleFlores3 };

            var collection = flores.GroupBy(f => f.Nome);

            foreach (var group in collection)
            {
                var list = group.ToList();

                //ShuffleFlores1.AddRange(list.GetRange(0, list.Count() / 3));
                //list.RemoveRange(0, list.Count() / 3);

                //ShuffleFlores2.AddRange(list.GetRange(0, list.Count() / 2));
                //list.RemoveRange(0, list.Count() / 2);

                //ShuffleFlores3.AddRange(list.GetRange(0, list.Count()));
                //list.RemoveRange(0, list.Count());

                for (int i = 0; i < allLists.Count; i++)
                {
                    int items = list.Count() / (3 - i);
                    allLists[i].AddRange(list.GetRange(0, items));
                    list.RemoveRange(0, items);
                }
            }

            Console.ReadKey();
        }

        static List<Flor> GetDummyFlores()
        {
            var list = new List<Flor>();

            var flores = new string[] { "Iris-versicolor", "Iris-virginica", "Iris-setosa" };

            for (int i = 0; i < flores.Length; i++)
            {
                list.AddRange(Enumerable.Range(50 * i , 50).Select(x => new Flor(flores[i], x)));
            }
            return list;
        }
    }

    class Flor
    {
        public string Nome { get; set; }
        public int DummyId { get; set; }

        public Flor(string nome, int dummyId)
        {
            this.Nome = nome;
            this.DummyId = dummyId;
        }

        public Flor() { }

        public override string ToString()
        {
            return $"{this.Nome} # {this.DummyId}";
        }
    }
}

The commented part does the same as the cycle for next, not needing the var allLists.

With 9 flowers of each type are the lists: inserir a descrição da imagem aqui

If you want the confused lists you’ll have to do later.

0

I imagine you can solve it in two ways.

Solution 1: Already knowing the amount of groups (in case, you know), you can solve with a foreach:

List<Flor> flores = Flor.GetFlores();

var rnd = new Random();
var query =
from i in flores
let r = rnd.Next()
orderby r
select i;

var versicolor = new List<Flor>();
var virginica = new List<Flor>();
var setosa = new List<Flor>();

foreach (var flor in query)
{
    if (flor.Nome == "Iris-versicolor")
    {
        versicolor.Add(flor);
    }
    else if (flor.Nome == "Iris-virginica")
    {
        virginica.Add(flor);
    }
    else if (flor.Nome == "Iris-setosa") //else 
    {
        setosa.Add(flor);
    }
}

Solution 2: Not knowing the number of groups, use the extension methods IEnumerable<T>.GroupBy and IEnumerable<T>.ToDictionary to group in a dictionary of names:

List flowers = Flower.Getflores();

var rnd = new Random();
var query =
from i in flores
let r = rnd.Next()
orderby r
select i;

Dictionary<string, List<Flor>> floresPorNome = query.GroupBy(f => f.Nome).ToDictionary(g => g.Key, g => g.ToList());

Browser other questions tagged

You are not signed in. Login or sign up in order to post.