Control break pattern

R

Roedy Green

Are there any classes or special techniques for handling a problem
like this?

You have a list sorted by some category. You want to do something
special prior to processes sing the first of a string of dups and
something special after.

It is sort of like a Visitor pattern except you want a start Group and
end Group method invoked as well as an item processor.

Then there is the generalisation, the control break where you have
several levels of keys.
 
S

Stefan Ram

Roedy Green said:
You have a list sorted by some category. You want to do
something special prior to processes sing the first of a string
of dups and something special after.

I would define an interface

interface GroupProcessor
{ public void beforeFirstItem();
public void item( final Item item );
public void afterLastItem(); }

And a Map from group to GroupProcessor:

final java.util.Map<Group,GroupProcessor> map
= new java.util.HashMap<Group,GroupProcessor>();

Initialize this map with implementations of GroupProcessor
and pass this map to the list processor:

final ListProcessor listProcessor
= new ListProcessor( map );

listProcessor.process( list );

This might be a special case of the Strategy pattern.
 
K

Kevin McMurtrie

Roedy Green said:
Are there any classes or special techniques for handling a problem
like this?

You have a list sorted by some category. You want to do something
special prior to processes sing the first of a string of dups and
something special after.

It is sort of like a Visitor pattern except you want a start Group and
end Group method invoked as well as an item processor.

Then there is the generalisation, the control break where you have
several levels of keys.

The answer to the first question can be found by looking at the
collision list walker in HashMap. That's a fairly standard design for
walking a one-way list while being able to look back at the previous
entry.

I call BS on the second question. It looks like homework rather than a
real-world condition, otherwise you would have called it by name (XML,
etc.).
 
M

Mark Space

Kevin said:
I call BS on the second question. It looks like homework rather than a
real-world condition, otherwise you would have called it by name (XML,
etc.).

lol... I get the feeling reading this list that it's been a while since
Roedy's been in school....
 
D

Daniel Pitts

Roedy said:
Are there any classes or special techniques for handling a problem
like this?

You have a list sorted by some category. You want to do something
special prior to processes sing the first of a string of dups and
something special after.

It is sort of like a Visitor pattern except you want a start Group and
end Group method invoked as well as an item processor.

Then there is the generalisation, the control break where you have
several levels of keys.
Sounds like a generalization of the visitor pattern to me. Think about
SAX implementations and how they work. That style of callback is pretty
much what you are talking about.
 
A

Andreas Leitgeb

Roedy Green said:
You have a list sorted by some category. You want to do something
special prior to processes sing the first of a string of dups and
something special after.

Since at seeing a so-far-unique item you cannot yet foresee if
it is the start of a group or a singleton, you need to delay the
processing of each item:

e.g.:
int[] some_ints={1,2,3,3,4}; int aux;
boolean group=false, notfirst=false;

for (int cur: some_ints) {
if (group) {
process(aux); if (aux!=cur) { endGroup(); group=false; }
} else if (notfirst) {
if (aux==cur) {group=true; startGroup(); } process(aux);
}
aux=cur; notfirst=true;
}
process(aux); if (group) { endGroup(); }


If your definition of "dups" is less strict, and includes
singleton items, then it's a bit simpler: (same vars as before)
startGroup();
for(int cur: some_ints) {
if (notfirst) { if (aux!=cur) { endGroup(); startGroup(); } }
notfirst=true; aux=cur; process(cur);
}
endGroup();

Then there is the generalisation, the control break where you have
several levels of keys.

I guess, the first approach can be extended:

int[] some_ints={1,2,3,3,4}; int aux;
boolean group1=false,group2=false,..., first=true;
for (int cur: some_ints) {
if (first) { aux=cur; first=false; continue; }
//repeat for N=1,2,...
if (groupN) {
if (!keymatchN(aux,cur)) { groupN=false; prepareEndGroupN(); }
} else {
if (keymatchN(aux,cur)) { groupN=true; prepareStartGroupN(); }
}
//end-repeat
doAllPreparedStartGroups(); // emit all the group starts
process(aux);
doAllPreparedEndGroups(); // emit all the group ends
aux=cur;
}

If there are several levels of keys, I wonder how the list can
be sorted by all of them at the same time, though, so probably
it will just group together the other keys, if two items subsequent
by the sorted key happen to have an equal other key.

These start-end-groups are then not necessarily properly
nesting, and I don't see how this would really work out in xml.
 
R

Roedy Green

I call BS on the second question. It looks like homework rather than a
real-world condition, otherwise you would have called it by name (XML,
etc.).

Back in the 60s the problem of dealing with control breaks spawned an
entire language, RPG. It had a peculiar column-dependent syntax.

We do less batch processing that in the olden days, but we summarise
data. Control breaks are considerably more difficult to get your head
around than a Visitor, so I would not sniff at the problem. As for
being a homework problem, I think only two of my teachers are still
alive.
 
D

David Zimmerman

Roedy said:
Back in the 60s the problem of dealing with control breaks spawned an
entire language, RPG. It had a peculiar column-dependent syntax.

I miss RPG (no really!)
 
M

Martin Gregorie

I miss RPG (no really!)

Jeez! I certainly don't.

It always struck me as the bastard offspring of crossing a machine-
independent assembler with Fortran IV. RPG III is about the most painful
way I know of writing a CRUD application.
 
D

David R Tribble

Roedy said:
Are there any classes or special techniques for handling a problem
like this?

You have a list sorted by some category. You want to do something
special prior to processes sing the first of a string of dups and
something special after.

It is sort of like a Visitor pattern except you want a start Group and
end Group method invoked as well as an item processor.

Then there is the generalisation, the control break where you have
several levels of keys.

Having actually coded this sort of thing in the past, I can say that,
yes,
this can be done.

You essentially have N nested loops, where N is the number of levels
you data breaks on. It's up to the inner loops to detect when the
break level occurs, and then terminate their loop level and allow the
next outer loop to advance to the next group.

Alternatively, you can manage the looping with an array of N elements,
where each element keeps track of the current break value for a level.
Then you can do all the work within a single loop, and the logic for
detecting group breaks occurs at the top of each loop.

There are a few subtleties about how to manage the groups, however,
and you have to make sure that you don't omit the processing of the
last element of each group, which can be tricky.

-drt
 
G

Gilbert

David said:
I miss RPG (no really!)

Actually so do I - it made control break processing easy. You knew when you
had the first record of a new group (L1 detail time) and when you had
processed the last of the group and you were about to start a new group
(L1-total time). You could also tell if the current record was the last of
a group through "lookahead" fields.

Great times

Regards
 
E

edmund yau

David R Tribble æ到:
Having actually coded this sort of thing in the past, I can say that,
yes,
this can be done.

You essentially have N nested loops, where N is the number of levels
you data breaks on. It's up to the inner loops to detect when the
break level occurs, and then terminate their loop level and allow the
next outer loop to advance to the next group.

Alternatively, you can manage the looping with an array of N elements,
where each element keeps track of the current break value for a level.
Then you can do all the work within a single loop, and the logic for
detecting group breaks occurs at the top of each loop.

There are a few subtleties about how to manage the groups, however,
and you have to make sure that you don't omit the processing of the
last element of each group, which can be tricky.

-drt

IT manager 蛇頭鼠眼edmund yau (email擬似[email protected])
全香港最濺IT Manager, 見你著西è£è¿”å·¥. 著得好éŽä½¢å°±å•ä½ å¤ ç«Ÿé»žè«—, æ­£å°äºº,
ç—´æ’šç·š
5:00pm俾個jobä½ åš, è·Ÿä½å°±è‡ªå·±åšåˆ°11點æžæŽ‚ä½¢, 第2日就å°ä½ , 話你æžå””掂, å””
撚洗放工呀

最撚柒就係呢æ¢å‹å•¦, æžå€‹çˆ›ç¶²å‡ºé»Ž, 大家去ç‡ä¸‹:
網å€æ“¬ä¼¼www.funzy.com

有幾爛? 仆街, 用IE6開會死機架, 真係唔撚知用乜野skillå¯ä»¥å¯«æ’šåˆ°hangæ©Ÿ.

æˆæ¢teamæœ9晚10, æžå€‹çˆ›ç¶²å¾—個2個functionä»”, 唔係hang機就係死link, 仲話寫
webè¦éƒ½å””知乜撚野skill set, 食屎啦, å°å­¸ç”Ÿå¯«å€‹web都唔撚會hang機啦

個個åŒäº‹æƒ³æ”¾å·¥éƒ½è¦é©šå‘¢æ¨£é©šå€‹æ¨£, 你張你oçš„é’春濺賣就唔撚好å«äººä¸€é½ŠåŒä½ æ¿º
è³£, 人地都有屋ä¼, 你唔撚放工就你o既事, 除撚左打工都唔撚知æžå€‹web未, 屎å‘關刀

大家多多張呢個網發佈出去, è²è¨Žå‘¢ç¨®å°äºº



Counter
1
 
J

John W Kennedy

Roedy said:
Back in the 60s the problem of dealing with control breaks spawned an
entire language, RPG. It had a peculiar column-dependent syntax.

And before RPG there was FARGO.
We do less batch processing that in the olden days, but we summarise
data.

Which is why IBM has QMF nowadays.
--
John W. Kennedy
"There are those who argue that everything breaks even in this old
dump of a world of ours. I suppose these ginks who argue that way hold
that because the rich man gets ice in the summer and the poor man gets
it in the winter things are breaking even for both. Maybe so, but I'll
swear I can't see it that way."
-- The last words of Bat Masterson
 
J

John W Kennedy

Martin said:
Jeez! I certainly don't.

It always struck me as the bastard offspring of crossing a machine-
independent assembler with Fortran IV. RPG III is about the most painful
way I know of writing a CRUD application.

RPG III is a mess, but RPG II and the original RPG do a fine job for a
restricted (but large) set of batch applications.
 
M

Martin Gregorie

RPG III is a mess, but RPG II and the original RPG do a fine job for a
restricted (but large) set of batch applications.
I never used RPG II.

RPG III was sort of OK for batch and reporting tasks, but I still
disliked the fixed field formats and indicators. The OS/400 source
editor's syntax awareness made it usable: I'd have really hated it
otherwise.

There was a much more concise and friendly alternative: NCC Filetab.

It never seems to have been as well known as it deserved. Programs were
more concise than RPG equivalents and were interpreted rather than
compiled, yet it ran nearly as fast as compiled COBOL. It used extended
decision tables to define processing logic and supported up to 10(!)
levels of control breaks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top