473,738 Members | 1,949 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Efficient creation of "refined" list<T>, from old list<T>

Hi!

Sorry for the bad subject line... Here's what I mean. Suppose we deal
with C++ standard integers lists (the type is indifferent). We have a
function f, declared as

list<intf(int);

Now we have an integer list p, say. For each element x in p, we want to
repace x with f(x) to get a new, possibly larger, integer list. Note
that we do not want a list of integer lists.

For instance, if p=[1,2,3] and f(x)=[x*x,x*x*x], we want to run
"apply(p)", after which p=[1,1,4,8,9,27]. In my particular application,
this step is thought of as a "refinement " of the information available
in the list. It's a perfect situation for recursion, but the recursion
becomes too deep (generating a crash).

The code below does *not* work (it returns [1,1,1,4,8,9,27] -- that is,
one 1 too much). And it probably does more copying than necessary :/
And it's ugly. Any help on how to do this in a cleaner and more
elegant way is much appreciated!

#include <iostream>
#include <list>
#include <iterator>

list<intf(int x)
{
list<intl;
l.push_back(x*x );
l.push_back(x*x *x);
return l;
}
void apply(list<int& l)
{
list<int>::iter ator old_i = l.begin();
list<intresult = f(*old_i);
l.insert(old_i, result.begin(), result.end());

for (list<int>::ite rator i=++l.begin(); i!=l.end(); i++)
{
l.erase(old_i); // Now it's safe to erase this element
old_i = i; // We need to save i to compute next iterator
i++
result = f(*i);
l.insert(i, result.begin(), result.end());
}
l.erase(old_i);
}

int main()
{
list<intl1;
l1.push_back(1) ;
l1.push_back(2) ;
l1.push_back(3) ;
apply(l1);

for(list<int>:: iterator i=l1.begin(); i!=l1.end(); i++)
cout << *i << " ";
cout << endl;
return 0;
}

Oct 12 '06 #1
3 2128
This is better. But probably there are far cleaner ways of doing it.
void apply(list<int& l)
{
list<int>::iter ator i=l.begin();

while(i != l.end())
{
list<int>::iter ator tmp_it = i;
list<intresult = f(*i);
l.insert(i, result.begin(), result.end());
i++;
l.erase(tmp_it) ;
}
}

Oct 12 '06 #2
ja****@gmail.co m wrote:
Sorry for the bad subject line... Here's what I mean. Suppose we deal
with C++ standard integers lists (the type is indifferent). We have a
function f, declared as

list<intf(int);

Now we have an integer list p, say. For each element x in p, we want
to repace x with f(x) to get a new, possibly larger, integer list.
Note that we do not want a list of integer lists.
You should probably reformulate this in terms of iterators. It will
be much easier to comprehend and it will essentially become your
algorithm.
For instance, if p=[1,2,3] and f(x)=[x*x,x*x*x], we want to run
"apply(p)", after which p=[1,1,4,8,9,27]. In my particular
application, this step is thought of as a "refinement " of the
information available in the list. It's a perfect situation for
recursion, but the recursion becomes too deep (generating a crash).
There is no need for recursion. A simple loop should do. Just as
you have written it, erasing the element and inserting the "refined"
list in its place should be just fine. To speed it up, replace the
'erase + insert_1st' with 'assign'.

I am sure the following contains problems I've not found, it's up to
you to find them and debug it further...

#include <iostream>
#include <iterator>
#include <list>
using namespace std;

template<class C, class F>
void refine(C &what, F how)
{
// assuming that F returns a C
typename C::iterator cb = what.begin(), ce = what.end();
while (cb != ce)
{
typename C::value_type val = *cb;
C c = how(val);
if (!c.empty())
{
typename C::iterator b = c.begin(), e = c.end();
*cb++ = *b++;
while (b != e)
what.insert(cb, *b++);
}
else
{
cb = what.erase(cb);
}
}
}

list<intf(int i)
{
int ii_iii[] = { i*i, i*i*i };
return list<int>(ii_ii i, ii_iii+2);
}

int main()
{
list<intonetwot hree;
onetwothree.pus h_back(1);
onetwothree.pus h_back(2);
onetwothree.pus h_back(3);

refine(onetwoth ree, f);

std::copy(onetw othree.begin(), onetwothree.end (),
ostream_iterato r<int>(std::cou t, ","));
}
The code below does *not* work (it returns [1,1,1,4,8,9,27] -- that
is, one 1 too much). And it probably does more copying than necessary
:/ And it's ugly. Any help on how to do this in a cleaner and more
elegant way is much appreciated!

[..code I didn't want to fix redacted..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 12 '06 #3
In article <11************ *********@m7g20 00cwm.googlegro ups.com>,
ja****@gmail.co m wrote:
Hi!

Sorry for the bad subject line... Here's what I mean. Suppose we deal
with C++ standard integers lists (the type is indifferent). We have a
function f, declared as

list<intf(int);

Now we have an integer list p, say. For each element x in p, we want to
repace x with f(x) to get a new, possibly larger, integer list. Note
that we do not want a list of integer lists.

For instance, if p=[1,2,3] and f(x)=[x*x,x*x*x], we want to run
"apply(p)", after which p=[1,1,4,8,9,27]. In my particular application,
this step is thought of as a "refinement " of the information available
in the list. It's a perfect situation for recursion, but the recursion
becomes too deep (generating a crash).
This is what I started with based on your description (without looking
at your code.)

list<intf( int i ) {
list<intresult;
result.push_bac k( i * i );
result.push_bac k( i * i * i );
return result;
}

template < typename InIt, typename OutIt, typename Op >
void apply( InIt first, InIt last, OutIt result, Op fn )
{
}

int main() {
int input[] = { 1, 2, 3 };
vector< int result;
apply( input, input + 3, back_inserter( result ), &f );
cout << "result == " << result.size() << "\n";
assert( result.size() == 6 );
assert( result[0] == 1 );
assert( result[1] == 1 );
assert( result[2] == 4 );
assert( result[3] == 8 );
assert( result[4] == 9 );
assert( result[5] == 27 );
}

Now it's simply a matter of filling in the "apply" function. I have to
run through the first container (from 'first' to 'last') calling 'fn' on
each item. This returns a list of interim results which I must then copy
into the result...

template < typename InIt, typename OutIt, typename Op >
void apply( InIt first, InIt last, OutIt result, Op fn )
{
while ( first != last ) {
list<intinterim = fn( *first++ );
copy( interim.begin() , interim.end(), result );
}
}

Note, this apply can use any sort of input container, output to any sort
of container and perform an operation that produces any number of
results (though it must return a list<int>.) You could, for example,
output directly to cout by providing a ostream_iterato r as the third
argument. :-)
The code below does *not* work (it returns [1,1,1,4,8,9,27] -- that is,
one 1 too much). And it probably does more copying than necessary :/
And it's ugly. Any help on how to do this in a cleaner and more
elegant way is much appreciated!

#include <iostream>
#include <list>
#include <iterator>

list<intf(int x)
{
list<intl;
l.push_back(x*x );
l.push_back(x*x *x);
return l;
}
void apply(list<int& l)
{
list<int>::iter ator old_i = l.begin();
list<intresult = f(*old_i);
l.insert(old_i, result.begin(), result.end());

for (list<int>::ite rator i=++l.begin(); i!=l.end(); i++)
{
l.erase(old_i); // Now it's safe to erase this element
old_i = i; // We need to save i to compute next iterator
i++
result = f(*i);
l.insert(i, result.begin(), result.end());
}
l.erase(old_i);
}

int main()
{
list<intl1;
l1.push_back(1) ;
l1.push_back(2) ;
l1.push_back(3) ;
apply(l1);

for(list<int>:: iterator i=l1.begin(); i!=l1.end(); i++)
cout << *i << " ";
cout << endl;
return 0;
}
OK, I see you are trying to replace the items in the list while
iterating over it. I think that is a needless complication. Better would
be to produce a new list and then simply swap them or assign the new
list to the old. Let's say however, that doing so was impossible for
some reason, then what would I do?
template < typename Seq, typename Op >
void apply( Seq& sequence, Op fn )
{
typename Seq::iterator pos = sequence.begin( );
while ( pos != sequence.end() ) {
typename Seq::value_type value = *pos;
pos = sequence.erase( pos );
typedef list< typename Seq::value_type InterimType;
InterimType interim = fn( value );
// can't use std::copy with an inserter or range insert here
// because I can't get a valid iterator back out of it.
for ( typename InterimType::it erator it = interim.begin() ;
it != interim.end(); ++it ) {
pos = sequence.insert ( pos, *it );
++pos;
}
}
}

The above will work with most sequences i.e., vector, deque, & list. To
do that, I did have some complications that I wouldn't have had if I
only wanted to support std::list. Then I could simply have used the
range inserter.

template < typename T, typename Op >
void apply( list<T>& sequence, Op fn )
{
typename list<T>::iterat or pos = sequence.begin( );
while ( pos != sequence.end() ) {
T value = *pos;
pos = sequence.erase( pos );
list< T interim = fn( value );
sequence.insert ( pos, interim.begin() , interim.end() );
}
}

The primary difference I see between your code and mine, is that you
tried to do the first iteration outside the loop. Apparently you made a
mistake in that code.

--
There are two things that simply cannot be doubted, logic and perception.
Doubt those, and you no longer*have anyone to discuss your doubts with,
nor any ability to discuss them.
Oct 12 '06 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
2496
by: Chris Tanger | last post by:
I am creating a class that has a method "Write" that I wish to make threadsafe. The method must block calling threads until the task performed in write is complete. Only 1 thread at a time can perform the task within "Write". 1-10 different threads may call "Write" simultaneously and continuously, some in a greedy manner. That is to say that some of the threads calling "Write" will take all they can get, while other threads may only call...
12
2029
by: Vaca Louca | last post by:
Hello, I write an ISAPI authentication module which uses Berkeley DB and want it to be as efficient as possible. Both ISAPI and BerkeleyDB use arrays of chars (char *) to pass and receive information. I know that C++ strings are supposed to be the "right" way to handle strings but I suspect that converting "char *" to string
14
1659
by: Jim Langston | last post by:
Which is more efficient (if either) MyHugeClass MyObject; for ( int i = 0; i < 1000; ++i ) { MyObject = SomeVal; Use MyObject; }
8
4905
by: dbamota | last post by:
What is the syntax in UDB db2, to create an index IX in table TBL "in tablespace TBSP" which is different from the tablespace of TBL ? TIA
19
5697
by: Materialised | last post by:
Hi everyone, What I am wanting to do, is to copy, a simple plain text file, to another file, but omitting duplicate items. The way I thought of doing this, involved copying all the items into a array, and then looping through that array looking for duplicates, removing them, and then writing to another file. This seems a very long and drawn out way of doing this to me, and also I
6
3204
by: m | last post by:
Hello, I have an application that processes thousands of files each day. The filenames and various related file information is retrieved, related filenames are associate and placed in a linked list within a single object, which is then placed on a stack(This cuts down thread creation and deletions roughly by a factor of 4). I create up to 12 threads, which then process a single object off of the stack. I use a loop with a boolean...
7
1318
by: Kay Schluehr | last post by:
I want to manipulate a deeply nested list in a generic way at a determined place. Given a sequence of constant objects a1, a2, ..., aN and a variable x. Now construct a list from them recursively: L = ]...]] The value of x is the only one to be changed. With each value of x a new instance of L is needed so that we actually have a function: L = lambda x: ]...]]
44
3379
by: petermichaux | last post by:
Hi, I have been using the following line of code to create an object called "Serious" if it doesn't already exist. if (Serious == null) {var Serious = {};} This works in the scripts I use it but but www.jslint.com is not happy with me.
12
1726
by: pedagani | last post by:
Dear comp.lang.c++, Could you make this snippet more efficient? As you see I have too many variables introduced in the code. //Read set of integers from a file on line by line basis in a STL set //fp is pre-defined for(;!fp.eof();) { string linestr;
0
8968
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9334
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9208
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8208
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6053
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4569
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3279
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2744
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2193
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.