I have create following string multidimensional array in java. which has top outer array is level(6 levels)and under each level has 4 different sub-level(4 sub levels) and each group has individual 10 set ,that have head and tails.I want to access level1->>sublevel1->set1-->head and tails ...level3->group4->set7->head and tails and so on up to level6->sublevel4->set10->head and tails.
final String[][][][] myStr = {
{
{
{"it", "it was over"},
{"on","work on it"},
},
{
{"very", "very good girl"},
{"all","all around"},
},
{
{
{"for", "good for you"},
{"are","are so long"},
},
{
{"with","with his cat"},
{"it", "it was over"},
}
},
...
{
{
{"get","get the cat"},
{"for", "good for you"},
},
{
{"on","work on it"},
{"can","can come here"},
},
{
{"as","as long as"},
{"but", "but not me"},
},
{
{"aunt","was my aunt"},
{"system", "her system was"},
}
}
};
Help me this problem , i think which is great appreciate to me.
Whatever your problem is, you shouldn't use such a kind of array, because your code will be impossible to understand and unmaintainable.
You should create a Level class, which would give access to a set or list of SubLevel instances, which should give you access to a set or list of Group instances, etc.
This will lead to much more readable code, and allow you to encapsulate behavior in these classes.
Say no to multi-dimensional array, Instead create custom classes if the relation is complex, else use simple Map.
I have no idea what you're actually trying to do, but it looks like you want to do a map from words to the sentence fragment it was found in - try a HashMap<String,String>
Related
I have a JSON string as follows (simplified):
{
"data":{
"fruit":[
{
"role":[
{
"role":"passive"
}
],
"objectType":"apple"
},
{
"role":[
{
"role":"active"
}
],
"objectType":"orange"
}
]
}
}
I would like to get objectType value where role is active. In this example the result would be orange. I've come up with the following code, however it doesn't return anything. How do I fix this?
$.data.fruit[?(#.role.role == 'active')]
Note that the number of elements in fruit array may vary and there is no guarantee that the last element would be correct.
At OP's request, here's the final, final answer!
$.data.fruit[?('active' in #..role..role)].objectType
On the off chance that it is a number, progressive levels in the stringification will each be indented by this many space characters (up to 10).
In the event that it is a string, progressive levels will be indented by this string (or its initial ten characters).
Usually, I avoid asking a new question as I always find a "close-enough" answer to my problem.
But this time I surprisingly have a fundamental and straightforward question - without any lead.
I have a straightforward MongoDB document that holds two arrays:
The 1st containing three numbers (ints) - each represent a code-number of a selected (predefined) question.
The 2nd was holding 3 Strings - that are the answers given by the user to these three correspondent questions.
For example, let's say subject code 12 is - "What's your 1st dog's name?", and the user's answer was: "Spiky", etc...
So I end up with something like:
{
"_id" : ObjectId("..."),
"questionCodesArray" : [
12,
56,
3
],
"answersArray" : [
"Spiky",
"go swimming",
"blabla.."
]
}
Now, I'd like to be able to allow the users to change their mind and choose a different question and supply a different answer to it.
For this, I need to have only the index of my element and access it via this index to change it using update() or findAndModify() [or any other method] and all the answers out there are "key-value style" which is not needed.
In simple Java I would've simply done something like:
questionsCodesArry[index] = newValue; and
answersArray[index] = newAnswerString;
All my attempts to write a descent query to do this simple index-based updating have failed.
Any help will be appreciated.
Thank you.
In plain MongoDB syntax what you need is this:
collection.update({
/*your filter goes here*/
}, {
$set: {
"questionCodesArray.<zero-based-index>": "new value"
}
})
I don't have a Java environment here to translate this into your driver's world. I might be able to do so tonight, though.
Still, I would definitely vote for a different, more natural and less error-prone design where you'd structure your data like so:
{
"_id" : ObjectId("59b635ffad44fad6662d8591"),
"answers" : [
{
"questionCode" : 12,
"answer" : "Spiky"
},
{
"questionCode" : 56,
"answer" : "go swimming"
},
{
"questionCode" : 3,
"answer" : "blabla.."
}
]
}
If that's an option for you I shall happily provide you the right update statement for this layout, too.
Well, after some trials here is a c&p complete and full method to change an array's element by a given index:
public boolean changeArrayValue(DB db, String collectionName, long id, String arrayNameKey, int index, Object newValue)
{
DBCollection collection = db.getCollection(collectionName);
DBObject query = new BasicDBObject("id",id);//unique id is recommended
DBObject update = new BasicDBObject("$set", new BasicDBObject(arrayNameKey+"."+index, newValue));
DBObject result = collection.findAndModify(query, null, null, false, update,true, true);
//Just for precaution
if(result == null)
return false;
return (((BasicDBList)result.get(arrayNameKey)).get(index)).equals(newValue);
}
As you can see the main issue lays in the $set line here: arrayNameKey+"."+index .
In the result I've put the needed flags to get the updated result, which is of type BasicDBList<Object>.
Pleases note that you'll have to add all the needed checks and validations according to your taste.
Enjoy..
For example:
class Vehicle {
Collection<Axle> axles;
}
class Axle {
Collection<Wheel> wheels;
}
class Wheel {
// I think there are dually rims that take two tires -- just go with it
Collection<Tire> tires;
}
class Tire {
int width;
int diameter;
}
I have a service through which I can get a collection of all Vehicle objects I know about. Now say I have a tire of a specific width and diameter, and I want to find a Vehicle which can take it. The simplistic way is to have a set of four nested loops, like so:
for (Vehicle vehicle : vehicles) {
for (Axle axle : vehicle.getAxles()) {
for (Wheel wheel : axle.getWheels()) {
for (Tire tire : wheel.getTires()) {
if (tire.width == targetWidth
&& tire.diameter == targetDiameter) {
// do something
break;
}
}
}
}
}
Is there a good design pattern for this? Or a better data structure to use? Would it be better to just keep an index somewhere of tire information mapped to vehicles?
edit: answering questions from comments
Do you have control over the structure of the data you receive from the service?
Yes
Do you need to search for different tires multiple times in the same data?
Yes
Is performance an issue?
Not especially
When you find the tire, do you just need to know which vehicle contains it or do you also need the axle and wheel?
Sometimes just the vehicle, sometimes just the axle -- two different contexts
Do you need the reference to the tire that was found?
Yes, in the cases where I need the axle
edit2:
Extending the metaphor further, to explain the two contexts above:
Context 1 -- I want to know the vehicle, so I can send a worker out to collect the vehicle and bring it back
Context 2 -- I want to know the axle and tire, because I am at the vehicle trying to do the work
You could flatten out the loops by using Java 8 streams.
vehicles.stream()
.flatMap(vehicle -> vehicle.getAxles().stream())
.flatMap(axle -> axle.getWheels().stream())
.flatMap(wheel -> wheel.getTires().stream())
.filter(tire -> tire.width == targetWidth
&& tire.diameter == targetDiameter)
.forEach(tire -> {
// do something
});
The nice thing about streams is that you could insert additional filter, filter, findAny, etc., calls pretty easily anywhere in the sequence.
I would inverse your logic and move the question into the Vehicle, unless of course you'd like to keep your objects thin for any other reason (in which case I'd personally wrap them with a thicker object to add any behaviour needed)
class Vehicle {
...
public Tire acceptsTire(Tire tire) {
}
}
from here on there are several possibilities, depending on how important this piece of business logic is in your domain in general.
If you'll have several actions you could probably just iterate as you had done in your sample. Or possibly in the same way as I suggested, keep cascade the question to the correct component. As long as you can live with the time complexity of doing this that should be alright.
If this check is something you'd usually do then you could have a reference to the type of tires you hold in the vehicle directly, this could be either your Tire collection, or you could pass a TireSpecification instance when constructing the Vehicle if for any reason you need to keep these separated (Your intention is not very clear in the question, is the tire on the car or just an spec of what could fit?)
Without changing your data structure you won't be able to make significant difference. You can add some syntactic sugar with lambdas, but it is essentially the same solution.
Things you could look at:
Your model allows for Vehicles with zero axles or hundred. While it depends on your business model it seems to weird.
Your model allows to have different axles in your vehicle, different wheels. Is it really necessary? Make sure which elements of your model should have their separate identity (currently each object has it) and which is just a value object.
Make sure you really need such detailed model. Currently you have two classes (Axle,Wheel), which only hold collections of inner objects. If they will be just simple JavaBean object with getAllInnerTypes() then you should consider removal of this class. It may even be the case that tire information should be stored almost directly in Vehicle class.
As long as there aren't too many items and/or performance is not a big issue, I would probably just go with the nested loops (or streams from John's answer).
Since you have two contexts for the search, you could pass the appropriate action to the search method - something like this (using loops in this case):
interface TireAction {
void doSomething(Vehicle v, Axle a, Tire t);
}
void findTireAndPerform(int targetWidth, int targetDiameter, TireAction action) {
for (Vehicle vehicle : vehicles) {
for (Axle axle : vehicle.getAxles()) {
for (Wheel wheel : axle.getWheels()) {
for (Tire tire : wheel.getTires()) {
if (tire.width == targetWidth && tire.diameter == targetDiameter) {
action.doSomething(vehicle, axle, tire);
break;
}
}
}
}
}
}
void someMethod() {
...
findTireAndPerform(width, diameter, (v, a, t) -> {
// send worker to 'v'
});
...
findTireAndPerform(width, diameter, (v, a, t) -> {
// work on 'a' and 't'
});
}
I need the data that caused the rule to be fired from the "When" section in the "Then" section of the rule. For instance, if I wanted to make note of all bad apples in a store if there were more than 50, this is how I'm doing it.
Rule "Detect Bad Apples"
When
s : Store( numberOfBadApples() > 50 )
Then
// Print out a list of the bad apples
To make it a little more complicated I have multiple rules that will overwrite. Otherwise, I would store the data into a variable in the Store class.
Is there a better way to do this? I've been reading through the Drools 6.2 Documentation, but I'm still confused.
---EDIT----
The Store Class in Java would look like:
public class Store {
private ArrayList<Apple> appleList;
// The appleList would be filled in another method
public int numberOfBadApples() {
int badAppleCount = 0;
for (Apple apple : appleList) {
if (apple.isBad()) {
badAppleCount++;
}
}
return badAppleCount;
}
}
So in the "Then" statement in Drools, I want to return a list of the apples (the bad ones, in this case) that caused the rule to be fired.
I have an array list declared like this:
val aName = new ArrayList
I add names in this array via the add().
When I print them, I only want to print specific names (e.g. all with names "Charlie" and working at the department Finance).
In my for loop, I have this:
for (m: aName.filter[!CDirectoryFacade::instance.isNameUsed(toString)])
{
print(m)
}
The loop above did not print the name at all.
Because my function isNameUsed() did not receive the string as I expect, but rather it receives the address as a String
org.generator.myDsl.myDslGenerator#67bd0a26
However, I do not seem to have problem when I do not use filter().
for (m: aName)
{
if (!CDirectoryFacade::instance.isNameUsed(m))
{
print(m)
}
}
Can anyone suggest on how to use the filter() with Strings?
It's hard to tell because your code snippet doesn't provide any types and it is not clear where name comes from in the print expression.
But the code above should probably read like this:
for (m: aName.filter[!CDirectoryFacade::instance.isNameUsed(toString)])
{
print(m.name) // instead of print(name)
}
I could be even more concise:
aName.filter[!CDirectoryFacade::instance.isNameUsed(toString)].forEach[ print(name) ]