WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

X aufeinanderfolgende Zeichen in Vektor suchen

 

pooz
Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 04.05.09
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 14.07.2010, 18:44     Titel: X aufeinanderfolgende Zeichen in Vektor suchen
  Antworten mit Zitat      
Hi,

kurz und knackig:

Suche in Vektor
Code:
0     0     1     1     1     1     1     0     0     1     1

jene Stellen, die mindestens 4 x die "1" hintereinander enthält.

Also:
Start = 3
Ende = 7


Intention:
Suche in gegebenen Vektor jene Start- und Endpositionen, die immer mindestens 4 Samples lang (1 Sample = 1 Element) auf True waren.

Vielen Dank
Private Nachricht senden Benutzer-Profile anzeigen


denny
Supporter

Supporter



Beiträge: 3.853
Anmeldedatum: 14.02.08
Wohnort: Ulm
Version: R2012b
     Beitrag Verfasst am: 14.07.2010, 20:39     Titel:
  Antworten mit Zitat      
Hallo

z.B so:
Code:

Laenge  = 4
A       =  [0 ,0 ,1 ,1 ,1,1 ,1,0,0,1,1]
Start  = strfind([0 A], [0 ones(1,Laenge)])
Ende  = strfind([A 0], [ones(1,Laenge) 0])+Laenge-1
 
Private Nachricht senden Benutzer-Profile anzeigen
 
josekamara
Forum-Meister

Forum-Meister


Beiträge: 529
Anmeldedatum: 26.04.08
Wohnort: München
Version: ---
     Beitrag Verfasst am: 14.07.2010, 21:02     Titel:
  Antworten mit Zitat      
Hier bitte:
Code:

laenge = 4;

x = [0   0   1    1    1    1    1    0    0    1    1];
p = ones(1,laenge);

A=[];
B=[];

for i=1:(length(x)-laenge)
   
    A(end+1,:) = x(i:i+laenge-1) - p;
   
    if A(end,:) == zeros(1,laenge)
    B(end+1,:) = [i    i+laenge-1];
    end
   
end
 


B Stellt Alle Start und Ende für den zugehörigen Vektor. bei laenge 4 kriegst du 2 Fälle und bei laenge 5 kriegst du einen Fall von 3 bis 7.

Gruß

Jose
_________________

Simulation

Zuletzt bearbeitet von josekamara am 14.07.2010, 21:06, insgesamt einmal bearbeitet
Private Nachricht senden Benutzer-Profile anzeigen
 
pooz
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 04.05.09
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 14.07.2010, 21:04     Titel:
  Antworten mit Zitat      
@denny
Tatsache! Nicht schlecht. Vorallem liefert Tic/Toc schnelle Zeiten.
Jedenfalls schneller als meine Methode.

Gibt es evtl eine noch effizientere Methode? Ich frage aus 2 Gründen:
Zum Einen möchte ich später diesen Algorithmus nach C portieren, zum Anderen wundert es mich, dass man einen Vektor-Vergleich (also finde A in B, wobei length(A)<length(B)) mit einem String-Befehl löst.

(Ich habe es vergeblich mit "ismember" und "intersect" versucht.)

Aber vielen Dank dafür!!
Private Nachricht senden Benutzer-Profile anzeigen
 
pooz
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 04.05.09
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 14.07.2010, 22:19     Titel:
  Antworten mit Zitat      
@Jose,

vielen Dank.

Deins funktioniert auch!
Bei sehr großen Vektoren allerdings benötigt das viel mehr Rechenzeit. Ich vermute, das liegt an der FOR-Schleife.

Ich bin allerdings auf der Suche nach einem rechengünstigen Algorithmus. Mit der Version von denny bin ich schon auf dem guten Weg, denke ich Smile
Private Nachricht senden Benutzer-Profile anzeigen
 
denny
Supporter

Supporter



Beiträge: 3.853
Anmeldedatum: 14.02.08
Wohnort: Ulm
Version: R2012b
     Beitrag Verfasst am: 15.07.2010, 09:20     Titel:
  Antworten mit Zitat      
Hallo

es gibt noch eine Möglichkeit über DIFF das zu lösen

Code:

Laenge = 4
A       =  [0 ,0 ,1 ,1 ,1,1 ,1,0,0,1,1]

dA     = [diff(A)];

Start = find(dA==1)+1
Ende   = find(dA==-1)


if isempty(Start)&&~isempty(Ende) ||...
 (~isempty(Start)&& Start(1) > Ende(1) )
 Start= [1 Start];
end

if  ~isempty(Start)&&isempty(Ende)||...
 (~isempty(Ende)&& Start(end) > Ende(end))
   Ende = [Ende length(A)]
end

posOk = (Ende-Start) >=Laenge

Start = Start(posOk)
Ende = Ende(posOk)

 
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 15.07.2010, 10:21     Titel:
  Antworten mit Zitat      
Hallo,

Denny's Methode ist schwer zu übertreffen:
Code:

Laenge  = 4
A       =  [0 ,0 ,1 ,1 ,1,1 ,1,0,0,1,1]
Start  = strfind([0 A], [0 ones(1,Laenge)])
Ende  = strfind([A 0], [ones(1,Laenge) 0])+Laenge-1
 

Das STRFIND auch mit nicht-CHAR-Arrays arbeitet ist sehr praktisch und sollte in der Dokumentation deutlicher betont werden.
Eine Schwachstlle ist "[0 A]" und [A, 0]" für sehr große Vektoren A: Es werden im schlimmsten Fall (2*(length(A)+1)*8) Bytes im Speicher blockiert. Das ist zwar nur temporär, wenn der Rechner aber den RAM-Inhalt auf die Platte schreiben muss, wird es unerträglich langsam.
Ich vermute für riesige A ist dies sicherer (also schneller):
Code:
%%%%%%%%%%%% VORSICHT: BUGS! Siehe folgende Nachrichten!
Laenge  = 4
A       =  (rand(1, 1e8) > 0.5);  % Beispiel Daten
Start  = strfind(A, [0 ones(1,Laenge)]);
if all(A(1:Laenge)  == 1)
  Start = [1, Start];
end
Ende = strfind(A, [ones(1,Laenge) 0])+Laenge-1;
if all(A(end-Laenge+1:end)  == 1)
  Ende = [1, Ende];
end
 

Für kleine A ist das aber vermutlich langsamer.

Wenn Du das ganze in C schreibst, kannst Du die beiden STRFIND glichzeitig laufen lassen, was wohl etwa doppelt so schnell sein sollte.

Gruß, Jan

Zuletzt bearbeitet von Jan S am 01.08.2012, 02:24, insgesamt einmal bearbeitet
Private Nachricht senden Benutzer-Profile anzeigen
 
pooz
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 04.05.09
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 15.07.2010, 17:45     Titel:
  Antworten mit Zitat      
Danke, ihr Beiden.

@denny:
Dein neuer Algo findet nur das erste Paar. Weitere Folgen, die auch die Bedingungen erfüllen, werden nicht angezeigt.

@Jan:
Ich komme nicht auf das gleiche Ergebnis:
Das leichteste, was ich beheben konnte war, auf den Lösungsvektor "Start" 1 zu addieren. Dann klappts.
Aber der "Ende"-Vektor fängt mit 1 an? Und das Ende einer letzten Folge ist mir auch nicht ersichtlich (siehe Ende(end))

Viele Grüße!
Private Nachricht senden Benutzer-Profile anzeigen
 
denny
Supporter

Supporter



Beiträge: 3.853
Anmeldedatum: 14.02.08
Wohnort: Ulm
Version: R2012b
     Beitrag Verfasst am: 15.07.2010, 23:13     Titel:
  Antworten mit Zitat      
Hallo pooz,

habe kleinen Fehler beim Abziehen gemacht, im Beispiel kommen ja 5 Einsen hintereinander, habe ja darauf getestet, und deswegen übersehen dass mit 4 Einsen es nicht funktioniert hat.

so jetzt muss es passen
Code:


Laenge= 4;
A        =  [0 ,0 ,1 ,1 ,1,1 ,1,0,0,1,1,1,1]

dA     = [diff(A)];

Start = find(dA==1)+1
Ende   = find(dA==-1)


if isempty(Start)&&~isempty(Ende) ||...
 (~isempty(Start)&& Start(1) > Ende(1) )
 Start= [1 Start];
end

if  ~isempty(Start)&&isempty(Ende)||...
 (~isempty(Ende)&& Start(end) > Ende(end))
   Ende = [Ende length(A)]
end

% musste eine 1 dazu addieren
posOk = (Ende-Start+1) >=Laenge

Start = Start(posOk)
Ende = Ende(posOk)
 
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 16.07.2010, 01:04     Titel:
  Antworten mit Zitat      
Hallo Pooz,

Stiimt, die letzte Version war fehlerreich. Nächster Versuch:
Code:

Laenge  = 4;
A       =  (rand(1, 1e8) > 0.5);  % Beispiel Daten
Start  = strfind(A, [0, ones(1, Laenge)]) + 1;
if all(A(1:Laenge)  == 1)
  Start = [1, Start];
end
Ende = strfind(A, [ones(1, Laenge), 0]) + (Laenge - 1);
if all(A(end - Laenge + 1:end)  == 1)
  Ende = [Ende, length(A)];
end
 


Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
pooz
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 04.05.09
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 19.07.2010, 19:21     Titel:
  Antworten mit Zitat      
Vielen, Ihr beiden.
@ Jan: Funktioniert!
@ Denny: Bei folgender Sequenz gibts einen Fehler:
Code:
A = [zeros(1,1020) 1 1 1 1];

Eine Idee?

Zusätzlich hätte ich eine 2. Frage passend dazu, an Alle:
Wie kann ich am besten/effizientesten/einfachsten nun alle Bereiche in Vektor A auf Null setzen, die diese Bedingung (Mindestlänge) nicht erfüllen? Oder andersherum formuliert: Wie kann ich einen neuen Vektor A_neu erstellen, der in den zurückgegebenen Intervallen -also von Start bis Ende- true ist, und überall anders false?


Ich habe das leider nur mit einer For-Schleife lösen können:
Code:
 
    A_neu = zeros(1,length(A));
    for l = 1:length(Start)
        A(Start(l):Ende(l)) = true;
    end
 


Danke für Eure Hilfe!
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 19.07.2010, 20:41     Titel:
  Antworten mit Zitat      
Hallo Pooz,

Du hast Denny geschrieben, dass es "einen Fehler gibt" - es ist immer praktisch auch zu lesen, wie die Fehlermeldung denn lautet.

Die gepostete FOR-Schleife läßt sich beschleunigen: Bisher ist "A_neu" ein DOUBLE Vektor, in den Du "true"-Werte schreibst. Diese werden intern von LOGICAL (eigentlich ein uint8) nach DOUBLE gecastet (heißt das so auf Deutsch?). Schneller wäre es, gleich ein LOGICAL Vektor zu erstellen:
Code:
A2 = false(1, length(A));
on = true;
for l = 1:length(Start)
    A2(Start(l):Ende(l)) = on;   % Nicht "A"
end

Ausserdem habe ich die Antwort der Funktion(!) TRUE abgespeichert, weil ein Funktionsaufruf einen größeren Overhead hat, als das Kopieren einer Variable.

Eine andere Lösung als die FOR-Schleife wäre CUMSUM:
Code:
A2 = zeros(1, length(A));
A2(Start) = 1;
A2(Ende) = -1;
A2 = logical(cumsum(A2));

Leider arbeitet CUMSUM nicht mit INT8 Vektoren, so dass man etwas Speicherplatz für den DOUBLE Vektor verschwendet.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
denny
Supporter

Supporter



Beiträge: 3.853
Anmeldedatum: 14.02.08
Wohnort: Ulm
Version: R2012b
     Beitrag Verfasst am: 19.07.2010, 22:48     Titel:
  Antworten mit Zitat      
Hallo pooz

Du hast recht , es kommt zu einem Fehler in der IF-Bedingung,
Zitat:

??? Attempted to access Ende(1); index out of bounds because numel(Ende)=0.


Habe Klammer falsch gesetzt, jetzt soll es laufen.
Code:

Laenge= 4;
% A        =  [0 ,0 ,1 ,1 ,1,1 ,1,0,0,1,1,1,1]
A = [zeros(1,1020) 1 1 1 1];

dA     = diff(A);

Start = find(dA==1)+1;
Ende   = find(dA==-1);


if ~isempty(Ende)&&( isempty(Start) ||...
 ~isempty(Start)&& Start(1) > Ende(1))
 Start= [1 Start];
end

if  ~isempty(Start)&&( isempty(Ende)||...
  ~isempty(Ende)&& Start(end) > Ende(end))
   Ende = [Ende length(A)];
end

% musste eine 1 dazu addieren
posOk = (Ende-Start+1) >=Laenge;

Start = Start(posOk);
Ende = Ende(posOk);
 
 
Private Nachricht senden Benutzer-Profile anzeigen
 
pooz
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 04.05.09
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.07.2010, 18:45     Titel:
  Antworten mit Zitat      
Vielen Dank an alle, für die Hilfe.

jetzt habe ich eine 2. Frage, passend dazu:

Wie kann ich nun die vielen Start&Ende-Paare, aus den jeweiligen Vektoren "Start" und "Ende" in einem Schritt zur Adressierung verwenden?
Zur Zeit gehe ich noch mit einer Schleife durch, und erhalte einzelnd ein Start&Ende-Paar, was ich zur Adressierung verwende:
Code:
% Start = (1, 5, 20);
% Ende  = (3, 9, 30);

for i = 1:length(Ende)
        x(Start(i):Ende(i)) = true;
end

Geht es effizienter? Vielleicht ohne Schleife?

Vielen Dank für eure Hilfe!
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 30.07.2010, 14:47     Titel:
  Antworten mit Zitat      
Hallo Pooz,

mir war so, als hätte ich das am 19.07.2010, 20:41 bereits beantwortet.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen

Gehe zu Seite 1, 2  Weiter

Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.