Zoeken in een List naar bepaalde waarde

Status
Niet open voor verdere reacties.

goedlichtJoost

Gebruiker
Lid geworden
7 mrt 2012
Berichten
477
Hallo allemaal,

Ik heb op dit moment de volgende situatie, en wordt een textveld gevuld met een "eind-waarde", bijvoorbeeld 7000.
Nu moet er een handeling uitgevoerd worden die elke keer een maximale waarde heeft van 3000. dus je krijgt dan 1 keer een handeling van 0 tot 3000 vervolgens van 3000 tot 6000 en vervolgens nog een keer van 6000 tot 7000.
Dit heb ik op de volgende methode opgelost:
Code:
            int i = 0;
            double temp = eindwaarde;
            while (temp - 3000 > 0)
            {
                //zetwerk (groter dan 3000mm)
                Beamfactory.createzetwerk(i*3000, (i+1*3000));
                temp = temp - 3000;
                i++;
            }
               // afsluitend deel
            Beamfactory.createzetwerk(i*3000,eindwaarde);

Nou dit werkt wel, echter heb ik nu een List met daarin oplopende Double waardes. (list item 1 is altijd kleiner dan list item 2 etc...) van 0 tot eindwaarde.
De hoeveelheid items in deze list is volledig variabel.

Nu zou ik graag willen hebben, dat de bovenstaande code (dus het opdelen in "stukkken" van max 3000) gecombineerd wordt met de list. Dus dat een stuk altijd de waarde heeft van een item in de list.

Voorbeeld:

eindwaarde is 8000
list is: 200 2000 4000 4500 7000

Er moeten dan de handelingen uitgevoerd worden:

Code:
Beamfactory.createzetwerk(0,2000);
Beamfactory.createzetwerk(2000,4500);
Beamfactory.createzetwerk(4500,7000);
Beamfactory.createzetwerk(7000, eindwaarde);

Dus de maximale stap is nog altijd 3000, maar wordt wel altijd "omlaag" gebracht naar een waarde in de List.

Kan iemand mij misschien uitleggen hoe ik dit het beste aan kan pakken?

Mvg
Joost
 
Laatst bewerkt:
Wat als je 0, 200, 2000, 6100, 12000 hebt? (gat van meer dan 3000)

0, 2000
6000,6100
9000, 12000

of

0, 2000
2000,5000
5000,6100
6100,9100
9100,12000

of wat anders?



en moet het in je voorbeeld code dan niet 4500 ipv 4000 zijn?
Code:
Beamfactory.createzetwerk(0,2000);
Beamfactory.createzetwerk(2000,4500);
Beamfactory.createzetwerk(4500,7000);
Beamfactory.createzetwerk(7000, 8000);
 
Oef pijnlijke fout, inderdaad moet het 4500 zijn in mijn voorbeeld.
Je kunt er vanuit gaan dat dit nooit voorkomt, een bredere dan 3000.
Ik hoop dat het een beetje duidelijk is, het is gewoon er moet gekeken worden naar de list

edit: mocht het wel het geval zijn, dan een MessageBox melding
 
zoiets als dit (snel in elkaar gezet, niet helemaal getest)

Code:
        static void Main(string[] args)
        {
            var doubles = new List<double> { 200, 2000, 4000, 4500, 7000 };
            var endValue = 8000;

            var stepHandler = new StepHandler(endValue, doubles);
            stepHandler.Handle();

            Console.ReadLine();
        }

ik gebruik een queue om de waarde van klein naar groot te bekijken (Peek() method) en indien nodig te gebruiken (Dequeue() method).

Code:
    public class StepHandler
    {
        private const int StepValue = 3000;
        private readonly int _endValue;
        private readonly Queue<double> _values;

        public int EndValue
        {
            get { return _endValue; }
        }

        public StepHandler(int endValue, List<double> values)
        {
            _endValue = endValue;

            values.Sort();
            _values = new Queue<double>(values);
            _values.Enqueue(endValue);
        }

        public void Handle()
        {
            if (_values.Count == 0)
                throw new Exception("no values to handle");

            double x = 0;
            double y = StepValue;

            bool valueWasSet = false;

            while (_values.Count > 0)
            {
                double max = x + StepValue;

                while (_values.Peek() <= max)
                {
                    y = _values.Dequeue();
                    valueWasSet = true;
                    if (_values.Count == 0)
                        break;
                }

                if (valueWasSet)
                {
                    Console.WriteLine("Creating Zetwerk... {0}, {1}", x, y);
                }
                else
                {
                    //throw new Exception("gap of more than 3000");
                }

                x = y;
                y = max + StepValue;
                valueWasSet = false;
            }
        }
    }


11t7nlz.png
 
Bloodshed,

Zoals altijd, begrijp ik het niet helemaal:P.

Waarom een queue? Wat is hier het voordeel van?
Je gaat de waardes eerst sorteren? (dit hoeft niet want waardes staan altijd al op grote).
Dan heb je twee waardes, begin en eind (begin is 0 eind is 3000... en vervolgens wordt begin 3000 en eind +3000..) dat snap ik, zoites had ik ook.
Maar wat is dan de Peek waarde? en de dequeue waarde? Waar zit nu eigenlijk de controle van, de grootste waarde in de List, kleiner dan de stapwaarde?
Dit zit volgens mij in de while, maar hoe dit dan precies werkt is voor mij onduidelijk.
Misschien een optie om dit te implementeren in de door mij gegeven code?

Alvast bedankt!

gr
Joost
 
1)
Een queue is een rij, wat er het eerste in gaat, komt er ook weer als eerste uit.

(Enqueue: item bij de rij aansluiten)
(Dequeue: item vooraan de rij verwijderen, method return = value)
(Peek: kijken wat er vooraan staat, zonder deze te verwijderen)

Dat is in dit geval handig want elke waarde heb je maar 1x nodig. En je hoeft niet met index te werken want je pakt ze er gewoon 1 voor 1 uit.

Code:
var item = queue.Dequeue();
is gelijk aan
Code:
var item = list[0];
list.RemoveAt(0);


2)
Sort is eigenlijk gewoon een gewoonte. Een sort voor de zekerheid omdat de code in de class er afhankelijk van is en het mogelijk is de waardes 'unsorted' aan te leveren.


3)
Ik zal even wat herschrijven, aangezien wat ik vorige week geplaatst had was snel snel werk.

In principe heb je de x,y = 0,3000 om te beginnen, de y wordt aangepast aan de waarde die uit de rij wordt gehaald, tot en met 3000. Dus alles onder of gelijk aan 3000 wordt uit de rij gehaald. (daar is de peek voor, eerst kijken en dan handelen) en zo gaat het door tot dat de rij leeg is.

Na een stap van de aangegeven 3000 max, krijg je de nieuwe loop met x als de y waarde van de vorige stap, en die nieuwe y is x+3000.

(ik zal het even herschrijven hoe ik het eigenlijk zou moeten doen, als ik de vorige week meer tijd had, ik zie ook een foutje wat met de voorbeeld getallen toevallig niets uit maakte :P)
 
Ik ga voortaan m'n voorbeelden maar opslaan, is ook gemakkelijker om door verschillende classes heen te bladeren, past meer op je scherm, en kun je het project makkelijk geheel downloaden:
https://github.com/Bloodshed/Examples/tree/master/FrameWorkHandler/FrameWorkHandler

Code:
public class FrameWorkProcessor
{
	private int _stepSize;

	public int StepSize
	{
		get { return _stepSize; }
		set
		{
			if (value < 1)
				throw new ArgumentException("the stepsize cannot be smaller than 1");

			_stepSize = value;
		}
	}

	public FrameWorkProcessor(int stepSize)
	{
		StepSize = stepSize;
	}
	public FrameWorkProcessor()
		: this(3000)
	{

	}

	public void Process(List<double> collection, int endValue)
	{
		if (collection == null)
			throw new ArgumentNullException("collection");

		collection.Sort();

		var queue = new Queue<double>(collection);
		queue.Enqueue(endValue); //add endValue to the end of the queue
		
		double min = 0;
		double max = StepSize;

		while (queue.Count > 0)
		{
			bool valueWasDequeued = false;

			while (queue.Peek() <= (min + StepSize))
			{
				max = queue.Dequeue();
				valueWasDequeued = true;

				Console.WriteLine("debug: the value '{0}' was dequeued...", max);

				if (queue.Count == 0) //if the last item was dequeued break out of the loop
					break;
			}

			if (valueWasDequeued)
			{
				FrameWorkFactory.CreateFrameWork(min, max);
				//if factory is static, else pass in the factory in the contructor instead
				//instead of calling a static method, raising an event could be better
			}
			else
			{
				throw new StepSizeExceededException();
			}

			min = max;
			max += StepSize;
		}
	}
}
(link to class: https://github.com/Bloodshed/Exampl...eWorkHandler/Processors/FrameWorkProcessor.cs )



p.s. FrameWork == Zetwerk (english habbits die hard) ik gebruik de tooltip voor eventuele uitleg in dit geval

fuc9z6.png



Hoop dat je eruit komt, het is wat lastig uit te leggen stap voor stap op een forum, gebruik eventueel de debugger om te zien wat er precies gebeurt.
 
Bloodshed, helemaal duidelijk!
het werkt..
Echter, zoek ik nu nog een manier, om die gevonden min max waardes dan terug te sturen?
Ik heb namelijk verschillende soorten zetwerk met verschillende stepsizes.
Ik zou dus deze factory herhaalbaar willen gebruiken (juiste input geeft bijbehorende output)
Nu zit ik alleen te bedenken hoe ik dit dan het beste kan terug koppelen.

De output is dan een lijst van twee maten, ik kan dus twee listen laten vullen.
maar dan moet ik voor elk verschillende zetwerk een andere list aanmaken.

en met een return of ref waarde werken, dat werkt denk ik ook niet? want je moet meerdere malen terugkoppelen (meerdere max min).
Is het dan misschien het makkelijkste om een twee ref listen terug te koppelen? (min en max waarde list)

dus je krijgt dan iets van:
public void Process(List<double> collection, int Stepsize, ref List<double> minlijst, ref List<double> maxlijst)

dus dan laat je de lijsten die je hebt aangemaakt vullen, dan gebruik je ze (incombinatie met de BeamFactory juiste zetwerk functie) en vervolgens List.clear

Mvg
Joost
 
Ik zou geen 2 lists maken, ik zou een class maken die de min en max neemt en daar een list van maken dan hoef je niet de juiste max bij de juiste min de zoeken achteraf. Deze kun je dan returnen, ik gebruikt nooit ref of out of dit soort dingen.

Ook kun je gebruik gaan maken van events.

Ik zal nog eens een class maken die dit doet, zonder de method signature te wijzigen.

a) heb je de min, max values tussendoor ook nodig of alleen de gehele uitkomst als alles klaar is?
b) is je factory create method static of niet?
c) kan de endValue ook een double zijn?
 
Heb het tijdelijk even opgelost met een dubbele Ref List :p Maar als het beter kan dan sta ik daar altijd voor open!

Min en Max value's heb ik helemaal aan het einde nodig, want ik doe nu:
Code:
                List<double> minlist = new List<double>();
                List<double> maxlist = new List<double>();
                MaxMaatFactory.maxmaatuitvoeren(_lsysteem.hohlist, 7000, ref minlist, ref maxlist);
                for (int x = 0; x < minlist.Count; x++)
                {
                    Beamfactory.createonderrandboven(maxlist[x], minlist[x], _opstand.pytagoras - 70, _lsysteem.onderrand);
                }
Dus eerst de "berekening" vervolgens de bewerking.

Factory allemaal public, maar niets Static.

Endvalue zit altijd al in de List, dit is altijd de laatste waarde van de List.
dit is nooit een double, omdat dit al in millimeters nauwkeurig is. En in de aluminium bewerking is op de milimeter nauwkeurig al vrij lastig, laat staan op een tiende nauwkeurig. Dat kan ik het werkplaatspersoneel niet aan doen :d

Mvg
Joost
 
Updates: https://github.com/Bloodshed/Examples/tree/master/FrameWorkHandler/FrameWorkHandler

Als je nu de process method gebruikt krijg je een lijst terug met StepValues. Elke stepvalue heeft een min en een max waarde zodat je er makkelijk doorheen kunt loopen met een foreach en hoeft je niet met die index te werken.

(het samenvoegen van 2 apparte lists is wat lastig omdat je moet weten hoe het zit, ze moeten een gelijk aantal hebben en mogen niet appart gewijzigd worden, dit zijn nogal wat voorwaarden..)

In plaats van in de FrameWorkProcessor de Create method te gebruiken worden de waarden toegevoegd aan een lijst, en als alles is verwerkt wordt deze lijst dus terug gestuurd en kun je deze gebruiken. Wat dus ook zeer fijn is is dat je niet meer afhankelijk bent van de factory in je code daar.

Alles staat op de link bovenaan de post.

Hier heb je de combinatie van een min en max bij elkaar:
[cpp]namespace FrameWorkHandler.Models
{
public struct StepValue
{
private readonly double _min;
private readonly double _max;

public StepValue(double min, double max)
{
_min = min;
_max = max;
}

public double Min
{
get { return _min; }
}

public double Max
{
get { return _max; }
}
}
}[/cpp]



[cpp]using System;
using System.Collections.Generic;
using FrameWorkHandler.Factories;
using FrameWorkHandler.Processors;
using FrameWorkHandler.Processors.Another;

namespace FrameWorkHandler
{
class Program
{
private static FrameWorkFactory _frameWorkFactory;
private static AnotherFrameWorkFactory _anotherFrameWorkFactory;

static void Main(string[] args)
{
_frameWorkFactory = new FrameWorkFactory();
_anotherFrameWorkFactory = new AnotherFrameWorkFactory();

Console.WriteLine("The AnotherFrameWorkProcessor...\n");

var collectionA = new List<double> { 200, 2000, 4000, 4500, 7000 };
var collectionB = new List<double> { 20, 200, 400, 450, 700 };

var processor = new AnotherFrameWorkProcessor(3000);

//optional event see ProcessorStepSizeChanged method below
processor.StepSizeChanged += new StepSizeChangedEventHandler(ProcessorStepSizeChanged);

try
{
//A
Console.WriteLine("Processing Collection A with StepSize {0}", processor.StepSize);
var resultCollectionA = processor.Process(collectionA, 8000);

Console.WriteLine("Creating frame from the returned list using a foreach loop");
foreach (var stepValue in resultCollectionA)
{
_frameWorkFactory.CreateFrameWork(stepValue.Min, stepValue.Max);
}

Console.WriteLine();//br

//B
processor.StepSize = 300; //this will fire the event
Console.WriteLine("Processing Collection B with StepSize {0}", processor.StepSize);
var resultCollectionB = processor.Process(collectionB, 800);

Console.WriteLine("Creating frame from the returned list using a method on the collection class");
resultCollectionB.CreateUsingAnotherFrameWorkFactory(_anotherFrameWorkFactory);
//using the method on the collection class instead for cleaner code

}
catch (StepSizeExceededException ex)
{
Console.WriteLine(ex.Message);
}

Console.ReadLine();
}

static void ProcessorStepSizeChanged(object sender, StepSizeEventArgs e)
{
//optional
//you can update a status label for the user to see what the current stepsize is here
Console.WriteLine("The step size was changed to {0}", e.StepSize);
}
}
}[/cpp]


[cpp]using System;
using System.Collections.Generic;
using FrameWorkHandler.Models;

namespace FrameWorkHandler.Processors.Another
{
public sealed class AnotherFrameWorkProcessor
{
private int _stepSize;

public int StepSize
{
get { return _stepSize; }
set
{
if (value == _stepSize)
return;

if (value < 1)
throw new Exception("The StepSize cannot be less than 1.");

_stepSize = value;
OnStepSizeChanged();
}
}

public AnotherFrameWorkProcessor(int stepSize)
{
StepSize = stepSize;
}

public event StepSizeChangedEventHandler StepSizeChanged;

public StepValueCollection Process(List<double> collection, int endValue)
{
if (collection == null)
throw new ArgumentNullException("collection");

//TODO: validate endValue and see if it is really the highest value

collection.Sort();
var queue = new Queue<double>(collection);
queue.Enqueue(endValue); //add endValue to the end of the queue

double min = 0;
double max = StepSize;

var stepValues = new StepValueCollection();

while (queue.Count > 0)
{
bool valueWasDequeued = false;

while (queue.Peek() <= (min + StepSize))
{
max = queue.Dequeue();
valueWasDequeued = true;

if (queue.Count == 0) //if the last item was dequeued break out of the loop
break;
}

if (valueWasDequeued)
{
stepValues.Add(new StepValue(min, max));
}
else
{
stepValues.Clear();
throw new StepSizeExceededException(string.Format("There was a gap of '{0}' in the collection after value '{1}'. Please check your collection values before attempting again.", StepSize, max));
}

min = max;
max += StepSize;
}

return stepValues;
}

private void OnStepSizeChanged()
{
var handler = StepSizeChanged;
if (handler != null)
handler(this, new StepSizeEventArgs(StepSize));
}
}
}[/cpp]


(de AnotherFactory print de text in geel uit, gewoon om het verschil makkelijk te zien in het voorbeeld)

2ihkm6v.png
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan