Merging Object and List with Lambdas - list

I have a situation similar to the follows:
List<ObjectA> all = repository.findAll(Sort.by(Sort.Direction.ASC, "status"));
This find a list of object with three possible states: OPEN, CLOSED, PROGRAMMED
Now I must return a List that shows to the user the last PROGRAMMED object, the first OPEN object and all closed objects. I have writing something like that:
ObjectA programmed = all.stream().filter(isPROGRAMMED()).reduce((x,y) -> y).orElse(null);
ObjectA open = all.stream().filter(isOPEN()).findFirst().get();
List<ObjectA> closed = all.stream().filter(isCLOSED()).collect(Collectors.toList());
isOPEN(), isPROGRAMMED() and isCLOSED() are Predicate I have written as follows:
private static Predicate<ObjectA> isPROGRAMMED() {
return x -> x.getStatus().equals(Stato.PROGRAMMED);
}
private static Predicate<ObjectA> isOPEN() {
return x -> x.getStatus().equals(Stato.OPEN);
}
private static Predicate<ObjectA> isCLOSED() {
return x -> x.getStatus().equals(Stato.CLOSED);
}
Now I want just to merge the two object and the third list into one. List should contain programmed item (if present) open object (if present) and after that all closed items. I jave tried with Stream.of, Stream.concat but I always obtain some compilation errors..
Are there some way to do it with Lambdas and with few code?

If you want to avoid mutation of the closed list, then Stream IPA is one of the possible choices for this task.
It could be done like this:
public static List<ObjectA> merge(List<ObjectA> closed, ObjectA programmed, ObjectA open) {
return Stream.concat(Stream.of(programmed, open),
closed.stream())
.collect(Collectors.toList());
}
And as I've already mentioned in the comment if are not concerned about preserving the initial state of the closed list, then these objects can be added directly to the list. Since adding a new element at the beginning of the list is costly (if it's backed by the array), a better option will be make use of addAll() and add both values in one operation as Holger suggested :
closed.addAll(0, Arrays.asList(programmed, open));
Side note:
There's an inconsistency in how you are obtaining a programmed object and open object. If a programmed object doesn't exist your decided to return null. But if there's no open object, method get() will raise NoSuchElementException.
ObjectA programmed = all.stream().filter(isPROGRAMMED()).reduce((x,y) -> y).orElse(null);
ObjectA open = all.stream().filter(isOPEN()).findFirst().get();

Related

what /can/ you return from a function .. and expect it to be alive at arrival?

Once again I got cought on expecting a function to return a proper value and then be disapointed .. getting odd behavior and misleading debug-information instead.
It's fairly well known, that you cannot return a local variable from a function and expect it to arrive as you would expect. Testing
int i=2;
int k=4;
return make_pair<int,int>(i*i,k*k);
Does indeed return something respectable. But using more elaborate objects than simple types seems to catch me every time.
So, is there any formality that I can use for discriminating on what can and what cannot be returned safely from a function?
----------- added on edit: ------------
Here is the example that does not work, taken brutally out of context.
Problem-context is a (to be GUI) tree of rectangles for the screen.
Class node inherits from a base (rectangle) containing 3 pointers to plain types (again, used to make values stick) .. the base uses new in constructor
pair<node,node> node_handler::split( vector<node>::iterator& this_node, double ratio, bool as_horizontal ){
//this_node becomes parents to the split-twins
this_node->my_ratio=ratio;
double firstW, firstH;
double secW, secH;
glm::dvec2 afirst, asecond;
if(as_horizontal ){
firstW = *this_node->plWidth*LETTER_PIXEL_WIDTH;
firstH = *this_node->plHeight*LINE_PIXEL_HEIGHT*ratio;
afirst = *this_node->pPoint;
secW = firstW;
secH = LINE_PIXEL_HEIGHT*(*this_node->plHeight)*(1.0d-ratio);
asecond= afirst+glm::dvec2(0.0d, firstH);
}
else{
firstW = ratio*(*this_node->plWidth)*LETTER_PIXEL_WIDTH;
firstH = *this_node->plHeight*LINE_PIXEL_HEIGHT;
afirst = *this_node->pPoint;
secW = (1.0d*ratio)*(*this_node->plWidth)*LETTER_PIXEL_WIDTH;
secH = firstH;
asecond= afirst+glm::dvec2(firstW,0.0d);
}
return make_pair<node,node>( node(afirst ,firstW, firstH) , node(asecond ,secW, secH) ) ;
}
Technically, you can return anything from a function.
Now when you return a pointer or a reference to something that is only local, then you have a problem.
Solutions:
Return copies (OK with copy elision anyway)
Return shared_ptr<>/unique-ptr<> for something that must not be copied.
Return only basic types and pass to the function a reference to an object that might be modified.
Do not create something in the function that needs to be manually destroyed layer (say, a pointer created with new).
It's dawning on me, that classes containing pointer-members reasonably has to have custom copy/assignment operators. I never got to grips with the "rho" variable referred to in the books I read at the time ... "right_hand_object" it must be! That's my epiphany. It was following the business of the constructors and your talk of copyable objects that squeezed this old rho-problem of mine.
I'm sorry for having spread my frustration on you.

Delayed instantiation in C++

I'm trying to create a variable without instantiating the object.
In Python it would look like this:
graph = mymap[c] if c in mymap else Graph()
So I basically check if I already have that graph otherwise I create it. My understanding is that if I declare the following in C++ it will call the constructor and be wasteful.
Graph g;
So I'm trying to use pointers to avoid this "waste":
Graph* g;
if (graphs.find(c) == graphs.end()){
g = new Graph();
graphs[c] = *g;
} else {
g = &(graphs[c]);
}
std::cout << g << std::endl;
std::cout << &(graphs[c]) << std::endl;
The problem is that the addresses printed in the end do not match. In fact, my tests show that something weird is happening like a new instance of Graph is being created every time.
What am I doing wrong?
You actually don't have to do anything fancy here. You can simply do
Graph* g = &graphs[c];
The reason is that map::operator[] has the following behavior:
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
So if the key has an associated value already, you'll get a reference to that object. If that key does not yet exist, a value will be default constructed and inserted for you, and a reference to that new object will be returned.
Another answer already says the right way to do what you're asking, but I'll address (ha!) why the addresses don't match:
On this line:
graphs[c] = *g;
You're creating a COPY of the graph you just made with new that g points to, and that copy has a different address. You're then printing the address of the original and the address of the copy, so obviously they're at different addresses.
graphs[c] = ...
This code already does the allocation and construction of a (default) Graph object to be stored inside the map when there isn't one mapped to c already (which you already checked for).. the assignment after that just makes the Graph object it just created look like the one that you had previously created with the call to new.

Conditions on a constructors arguments [duplicate]

This question already has answers here:
How to handle failure in constructor in C++?
(8 answers)
Closed 7 years ago.
Is it possible to check the arguments of a constructor for certain constraints and if they're not met the object is not created and return a value to tell it failed to be created .
for instance .
Class Device
{
string id;
Device(string ID)
{
If (ID.Length != 7)
{
//Do not create Object
}
id == ID;
}
}
Here I only want 7 char long id String , not less not more ! if its not 7 char I don't want the Object created is it possible to do this ?
I couldn't think of any solution to this other than external function check which is something I want to stay away from !
The usual way would be to check the condition, and if it's not met, throw an exception.
Another possibility would be to accept an array of 7 characters, so the code won't compile if something else is passed. This tends to be trickier to get to work well in general though (e.g., it usually won't work if somebody passes an object of the wrong type, even something like a string that actually does contain 7 characters).
A sort of intermediate point would be to create a type specifically to hold your string of 7 characters, and throw an exception in its ctor if the length is wrong. This can give a little more granularity so it's easier to know what's wrong when the exception is thrown, as well as assuring that creating the Device object will succeed if you pass it a valid DeviceName (or whatever name you prefer) object.
You can throw an exception.
https://stackoverflow.com/a/7894215/2887128
Class Device
{
string id;
Device(string ID)
{
If (ID.Length != 7)
{
throw invalidObjectParametersException;
}
id == ID;
}
}
You could also adjust your design and wrap construction in some sort of factory.
One option I can think of is to throw an error if the condition is not met and catch that error in the function that creates the object.
Yes, you can implement a valid method, which will return if the created object is valid. In order to do that, without creating your real object, you would have to create an internal struct, which would become a private member of the owner class:
Class Device
{
struct DeviceImplementation {
string id;
Device owner;
DeviceImplementation (Device *owner, const string &id):
owner(owner),
id(id)
{
}
};
std::unique_ptr<DeviceImplementation> implementation;
public:
Device(const string &ID)
{
If (ID.Length != 7)
{
//Do not create Object
} else
implementation=std::unique_ptr<DeviceImplementation>(new DeviceImplementation(this, ID));
}
bool isValid() const {return implementation!=nullptr;}
}
No, a constructor can only return an object (or raise an exception).
If you want the chance to verify parameters or context, you should make:
a) the constructor private (so it cannot be called from outside the class anymore)
b) provide a static public method that returns an object (or, for example, NULL if it failed), and inside this method do your tests, and if they are successful call the private constructor and return the created object.
Of course, the outside code needs to able to handle a NULL return (or whatever you chose to do to signal that it failed).
This is a simple and common solution, but you can make up others with similar ideas.

How to change QJsonObject value in a QJson hierarchy without using copies?

I am currently using Qt5.0 with the core QJson library to handle some data for the program I am developing.
To set the scene for this question I will provide you with some JSON data that illustrates my problem:
{
"CLOCKS": [
{
"ID": "clk",
"MAX": 2e+08,
"MIN": 1e+07,
"VALUE": "no_clock"
},
{
"ID": "memclk",
"MAX": 2e+08,
"MIN": 1e+07,
"VALUE": "memclk"
}
]
}
Here we have a parent QJsonObject containing a single key 'CLOCKS'. The value for this key is a QJsonArray of QJsonObjects that contain a number of key/value pairs that contain my data.
If I wanted to retrieve the QJsonObject with id 'clk' I am currently using code like this:
// imagine m_data is my parent QJsonObject
QJsonArray clocks = m_data["CLOCKS"].toArray();
foreach (const QJsonValue & value, clocks) {
QJsonObject obj = value.toObject();
if (obj["ID"].toString() == "clk") {
return obj;
}
}
This works fine and the library has been great so far. However, I have started running into issues recently when I want to obtain a QJsonObject reference for modification instead of a copy.
So my question is, given the sample data provided how do I obtain a QJsonObject reference in order to modify the key/value pairs in the desired clock data object. The problem manifests itself, IMO due to the fact that you can obtain QJsonValueRefs, which are references to the value entries... but to actually access the data inside this (if the value is another array/object) you must convert using the toArray(), toObject() functions etc. This functions only return copies and not references creating a barrier to iterating down the object hierarchy with references.
The only way I have come up with so far to get around this is to create a copy of the entire "CLOCKS" QJsonArray, find the object I want then delete it and reinsert it with the changed data... and finally assign the entire array back to the "CLOCKS" key in the parent object. This seems cumbersome enough to me to me that I feel like I am doing something wrong and there must be a better way.
To support this here is what my code looks like so far... just to change the "VALUE" for one of the clock QJsonObjects:
QJsonArray resets = m_data.value(TAG_RESETS).toArray();
// get a copy of the QJsonObject
QJsonObject obj;
foreach (const QJsonValue & value, resets) {
QJsonObject o = value.toObject();
if (o.value(TAG_ID).toString() == id) {
obj = o;
break;
}
}
// modify the object
obj[TAG_VALUE] = "NEW VALUE";
// erase the old instance of the object
for (auto it = resets.begin(); it != resets.end(); ++it) {
QJsonObject obj = (*it).toObject();
if (obj.value(TAG_ID).toString() == id) {
resets.erase(it);
// assign the array copy which has the object deleted
m_data[TAG_RESETS] = resets;
break;
}
}
// add the modified QJsonObject
resets.append(obj);
// replace the original array with the array containing our modified object
m_data[TAG_RESETS] = resets;
I know this could be shortened a little bit but it still seems like there must be a better way to change a single value in a QJson object hierarchy without going to all this effort!!!
After wasting three hours of my life I can confirm that as of today this is still impossible with Qt 5.4. You can modify JSON objects, but not nested JSON objects.
The problem is that the code such as:
json["aa"].toObject()["bb"] = 123;
essentially means the following:
QJsonObject temp = json["aa"].toObject();
temp["bb"] = 123;
and since temp is not a reference but object (and toObject() doesn't return a reference), the assignment is compiled but then discarded.
Essentially it breaks down to the fact that it is impossible to obtain the reference to an object you just created, meaning you cannot create them from left to right, i.e. aa["bb"] -> aa["bb"]["cc"] etc - you cannot obtain reference to aa["bb"], only a copy of its value.
What IS possible though is to recreate the JSON with a new value added, as described here: https://forum.qt.io/topic/25096/modify-nested-qjsonvalue/4 - note that this keeps recreating the object each time it is called, and is essentially memory usage disaster, but this is all Qt currently allows.
According to information from Qt developer who actually wrote QJson in Qt5 -
What's currently included in Qt is a 'read-only' implementation to provide parsing facilities. He has an intention to extend design with 'references' support in future, but it's not yet done.
I have had a similar problem for a couple of days and I have managed to find a workaround which works for me and I thought I should share it here.
You can navigate to the object whose key-value you wish to update. Then use the "remove" method to delete the key-value pair and then use the "insert" method to insert it again with the new value.
This might ruin the order of key-value pairs in your object but since you will anyways access by a key, it should not be a problem.
The in-place changing of values is not supported as I found out the hard way :)

Receiving assert failure on Reference Call

(Disclaimer: I have removed the Qt tag in case the problem is in my syntax / understanding of the references involved here)
I have a foreach loop with an object Member. When I enumerate through the list and try to access a member field, the debugger stops and I get a message:
Stopped: 'signal-received' -
The assert failure is:
inline QString::QString(const QString &other) : d(other.d)
{ Q_ASSERT(&other != this); d->ref.ref(); }
I have checked if the member is NULL, and it isn't. I have tried re-working the code, but I keep failing on this simple call.
Some thing's I missed out. MemberList is a singleton (definitely initialized and returns a valid pointer) that is created as the application launches and populates the MemberList with Members from a file. When this is created, there are definitely values, as I print them to qDebug(). This page is literally the next page. I am unsure as to how the List items can be destroyed.
The code is as follows:
int i = 0;
QList<Member*> members = ml->getMembers();
foreach (Member* mem, members)
{
QString memID = mem->getMemberID(); // Crash happens here
QListWidgetItem *lstItem = new QListWidgetItem(memID, lsvMembers);
lsvMembers->insertItem(i, lstItem);
i++;
}
The Member classes get is as follows:
QString getMemberID() const;
and the actual function is:
QString Member::getMemberID() const
{
return MemberID;
}
The ml variable is received as follows:
QList<Member*> MemberList::getMembers()
{
return MemberList::getInstance()->memberList;
}
Where memberList is a private variable.
Final answer:
I decided to rework the singleton completely and found that I was not instantiating a new Member, rather reusing the previous object over and over. This caused the double reference. S'pose thats pointers for you. Special thanks to Troubadour for the effort!
If mem is not null it could still be the case that the pointer is dangling i.e. the Member it was pointing to has been deleted.
If Member inherits from QObject then you could temporarily change your QList<Member*> that is stored in ml (assuming that's what's stored in ml) into a QList< QPointer<Member> >. If you then get a null QPointer in the list after calling getMembers or at any point during the loop then the object must have been destroyed at some point.
Edit
As regards the singleton, are you sure it's initiliased properly? In other words does MemberList::getInstance() return a valid pointer or just a random uninitialised one?
Edit2
Since we've exhausted most possibilities I guess it must be in the singleton somewhere. All I can suggest is to keep querying the first item in the list to find out exactly where it goes bad.