I have two arrays that are not sorted: a float array (float[]), and a String array (String[]) for the descriptions.
I need to sort the float array from the highest value to the lowest, but the descriptions are in the String array and if I sort them, the String array won't be sorted accordingly.
In Processing, there is a sort(Array) function, but it only sorts one array.
How can I sort the float array and have the descriptions match?
float totalCount = 0;
float maxValue = 0;
String[] statusDescriptions = new String[finishStatusesJSON.size()];
float[] countData = new float[finishStatusesJSON.size()];
for (int i = 0; i < finishStatusesJSON.size(); i++) {
JSONObject finishStatusJSON = (JSONObject) finishStatusesJSON.get(i);
float count = finishStatusJSON.getFloat("count");
String status = finishStatusJSON.getString("status");
totalCount += count;
statusDescriptions[i] = status;
countData[i] = count;
// Max value of the table
if(maxValue < count) maxValue = count;
}
How to use a simple class to hold both pieces of data and keep it in one array for easier sorting. Sorting is supported by implementing the Comparable protocol.
class Status implements Comparable<Status> {
String status;
float count;
public Status(String status, float count) {
this.status = status;
this.count = count;
}
#Override
public int compareTo(Status s) {
if (this.count < s.count) {
return 1;
} else if (this.count > s.count) {
return -1;
}
return 0;
}
}
Status[] statusArray = new Status[finishStatusesJSON.size()];
for (int i = 0; i < finishStatusesJSON.size(); i++) {
JSONObject finishStatusJSON = (JSONObject) finishStatusesJSON.get(i);
Status status = new Status(finishStatusJSON.getString("status"), finishStatusJSON.getFloat("count"));
statusArray[i] = status;
}
Arrays.sort(statusArray);
One solution would be to create a class that contains your entries, i.e. that combines a float with its description. For example, if you store movies as strings and their scores as floats, you could create a class MovieScore that contains the movie description (the string) and its score (the float). You could make this class Comparable and then sort an array of MovieScores to achieve your goal.
Maybe you could use a Map<K,V> type of array, where the K would be the Float class, while the V would be the String class.
Thus, you could use the put(K,V) method, like below, and then, sort properly.
float count = finishStatusJSON.getFloat("count");
totalCount += count;
map.put( count, finishStatusJSON.getString("status") );
Although, it seems like you're talking about Processing, not Java.
Erratum: It might be better to use a SortedMap implementing class; since you would be able to put a Comparator directly into the constructor, or use the natural ordering, and the Map will sort itself.
If you still want to use a Map implementing class, then I suggest that you use Map's keySet() method, then follow the same algorithm as suggested in this answer.
However, I'm skeptical of using those classes in Processing, since it might be in fact invalid for its framework; but if it compiles and there is no execution error/exception, then it may be worth a try.
Related
I have a long list of lines in (possibly) random order. So basically:
struct Line
{
Vector StartPos;
Vector EndPos;
};
Now I'm looking for an efficient way to sort these lines so that they are sorted into spans. I.E. if line A's startpos matches Line B's endpos, it gets moved into the list immediately after line B. If nothing matches, it just goes to the end of the list to start a new span.
Right now I'm doing it brute force-- setting a flag variable if anything was changed, and if anything changed, sorting it again. This produces gigantically exponential iterations. Is there any faster way to optimize this so that I could conceivably keep the iterations down to listsize^listsize?
If you do not have lines that start or end at the same point maybe you can use dictionaries to reduce the look ups. Something like:
public class Line
{
public Point StartPos;
public Point EndPos;
public bool isUsed = false;
};
and then 1) create a dictionary with the key the endPos and the value the index of the element in you list, 2) for each element of the list follow the link using the dictionary. Something like:
List<List<Line>> result = new List<List<Line>>();
Dictionary<Point,int> dic= new Dictionary<Point,int>();
for (int kk = 0; kk < mylines.Count; kk++)
{
dic[mylines[kk].EndPos] = kk;
}
for (int kk = 0; kk < mylines.Count; kk++)
{
if (mylines[kk].isUsed == false)
{
var orderline= new List<Line>();
orderline.Add(mylines[kk]);
int mm = kk;
while (dic.ContainsKey(mylines[mm].EndPos))
{
mm = dic[mylines[mm].EndPos];
mylines[mm].isUsed = true;
orderline.Add(mylines[mm]);
}
result.Add(orderline);
}
}
This is a section of my code, I have an ArrayList of 10 objects called "bob" and I want to loop through them so that each of their names (a local integer defined in the bob class) to be put in the array named "names" in order.
for (bob b : bob) {
for (int i = 0; i < 10; i++){
names[i] = b.name;
}
}
I tried this approach:
for (bob b : bob) {
for (int i = 0; i < 10; i++){
names[i] = b[i].name; //I added the "[i]" after b attempting to loop through
//the arraylist but it does not work
}
}
the syntax does not seem to allow me to loop through the arraylist of the objects like that. I am a beginning programmer so please excuse my lack of programming knowledge. It would be very helpful if someone could at least give me an idea of where to go from here. Thank you in advance!
When dealing with ArrayList you need to use the set() and get() methods to access the contents of it. Here's a somewhat hamfisted attempt at recreating the scenario you describe. Hope it helps.
class Bob {
int name;
Bob() {
this.name = floor(random(10000));
}
}
void setup(){
ArrayList<Bob> alb = new ArrayList<Bob>();
for(int i = 0; i < 50; i++){ //populate ArrayList
alb.add(new Bob());
}
int[] names = new int[10];
for(int i = 0; i < names.length; i++){
names[i] = alb.get(i).name; // use get() method
}
for(int i = 0; i < names.length; i++){
print(names[i]);
print('\n');
}
}
Your question highlights two techniques for iterating over a collection: with or without, an index. Each is best suited for different data structures and scenarios. It takes some experience to decide when to use one or the other, and is also a matter of personal style.
It is common to write code like for( int x: myInts ) and then realize you want the index of the current item, which isn't available. Or conversely, to write code like for( int i=first; i<last; i++) and then become irritated because determining first and last is tedious, or prone to bugs.
Notice your code is a double-nested loop. It says "iterate over each item in the collection Bob, and then for each one, iterate over each item in the collection of names". So if Bob had ten items, this would iterate one hundred total times, probably not what you want. You need to rewrite as a single, non-nested for loop ...
If you decide to iterate without an index, then names should be some type of list, where you can add items using append(). Consider the StringList available in Processing. Otherwise if you decide to iterate with an index, then names could be an array, although it could still be a list if it was already populated with old values which you wish to overwrite. The following shows both techniques:
void setup()
{
ArrayList<String> baseList = new ArrayList<String>(10);
for( int i=0; i<10; i++ )
baseList.add( i, Integer.toString( i + (i*10) ) );
// Approach 1: Iterate without an index,
// build a list with no initial allocation and using append()
StringList namesList = new StringList();
for( String s : baseList )
{
namesList.append( s );
println( namesList.get( namesList.size()-1 ) );
}
// Approach 2: Iterate with an index,
// build a list using preallocation and array access
String[] namesArray = new String[10];
for( int i=0; i<10; i++ )
{
namesArray[i] = baseList.get(i);
println( namesArray[i] );
}
}
I'm trying to structure MATRIX class by following these instructions;
Constructors: write three constructors
Taking a list of vectors as comma separated argument list and converting these vectors from the first to the last to a matrix (Vector is another class to be explained below) and constructing a matrix from these vectors either creating them as columns or rows of the matrix determined by another parameter. (if 0 treat them as raw vectors, if 1 treat these vectors as columns of the matrix)
Taking an integer and producing an Identity matrix of dimension determined by that integer.
The following methods are invoked over a matrix object and takes another matrix or any other relevant parameter(s) as needed.
Here is my matrix class;
package p1;
public class Matrix{
public double myArray[][];
public Matrix(int b,double...vectors) {
this.myArray=vectors;
double myArray[][] = new double[vectors.length][];
int row = vectors.length;
int column = vectors[0].length;
for (int i = 0; i < row; i++) {
myArray[i] = new double[column];
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if(b==0)
{
myArray[i][j] = vectors[i][j]; // ERROR HERE
}
else
{
myArray[j][i] = vectors[i][j]; // ERROR HERE
}
}
}
}
public Matrix(int d){
double myArray[][]=new double[d][d];
}
}
I've shown the errors in my code. I cannot integrate two vectors in one 2D array to make it equal to matrix.
Here is my implementation
However, it is a bit slow when analyzing the textfile,
Anyone have a better idea or better data structure to implement Random writing?
Im not using the STL library so dun worry about the syntax.
instead of using push_back, vector here is using .add
randomInteger will generate randome integer between ranges
I would like to produce 2000 character if possible;
I think the slowest part is reading the file char by char?
void generateText(int order, string initSeed, string filename){
Map<string , Vector<char> > model;
char ch;
string key;
ifstream input(filename.c_str());
for(int i = 0; i < order; i++){
input.get(ch);
key+=ch;
}
while(input.get(ch)){
model[key].add(ch);
key = key.substr(1,key.length()-1) + ch;
}
string result;
string seed = initSeed;
for(int i = 0;i<2000;i++){
if (model[seed].size() >0) {
ch = model[seed][randomInteger(0, model[seed].size()-1)];
cout << ch;
seed = seed.substr(1,seed.length()-1) + ch;
}
else
return;
}
}
You need to determine that it is taking too long. (How is this code not running in less than a second on an average laptop?)
If it is, you need to profile.
For example, a likely candidate is the cost of generating random numbers...
You'll only disprove me by profiling ;)
I think it is a bit slow because it creates lots of temporary strings during the analysis phase.
for(int i = 0; i < order; i++){
input.get(ch);
key+=ch; // key = key + ch, at least one new string created
}
while(input.get(ch)){
model[key].add(ch); // key copied to hash table
key = key.substr(1,key.length()-1) + ch; // a couple of temp strings created
}
You could do instead like this:
char key[order + 1]; // pseudo code, won't work because order is not constant
key[order] = 0; /* NUL terminate */
for (int i = 0; i < order; i++) {
input.get(key[i]);
}
while (!(input.eof())) {
for (int j = 0; j < order - 1; k++) {
key[j] = key[j + 1];
}
input.get(key[order]);
model[key].add(ch);
}
Here the only string that is actually created is the string that ends up as a key in the hash table. The key is rotated in a simple character array, avoiding string temporaries.
The environment: I am working in a proprietary scripting language where there is no such thing as a user-defined function. I have various loops and local variables of primitive types that I can create and use.
I have two related arrays, "times" and "values". They both contain floating point values. I want to numerically sort the "times" array but have to be sure that the same operations are applied on the "values" array. What's the most efficient way I can do this without the benefit of things like recursion?
You could maintain an index table and sort the index table instead.
This way you will not have to worry about times and values being consistent.
And whenever you need a sorted value, you can lookup on the sorted index.
And if in the future you decided there was going to be a third value, the sorting code will not need any changes.
Here's a sample in C#, but it shouldn't be hard to adapt to your scripting language:
static void Main() {
var r = new Random();
// initialize random data
var index = new int[10]; // the index table
var times = new double[10]; // times
var values = new double[10]; // values
for (int i = 0; i < 10; i++) {
index[i] = i;
times[i] = r.NextDouble();
values[i] = r.NextDouble();
}
// a naive bubble sort
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
// compare time value at current index
if (times[index[i]] < times[index[j]]) {
// swap index value (times and values remain unchanged)
var temp = index[i];
index[i] = index[j];
index[j] = temp;
}
// check if the result is correct
for (int i = 0; i < 10; i++)
Console.WriteLine(times[index[i]]);
Console.ReadKey();
}
Note: I used a naive bubble sort there, watchout. In your case, an insertion sort is probably a good candidate. Since you don't want complex recursions.
Just take your favourite sorting algorithm (e.g. Quicksort or Mergesort) and use it to sort the "values" array. Whenever two values are swapped in "values", also swap the values with the same indices in the "times" array.
So basically you can take any fast sorting algorithm and modify the swap() operation so that elements in both arrays are swapped.
Take a look at the Bottom-Up mergesort at Algorithmist. It's a non-recursive way of performing a mergesort. The version presented there uses function calls, but that can be inlined easily enough.
Like martinus said, every time you change a value in one array, do the exact same thing in the parallel array.
Here's a C-like version of a stable-non-recursive mergesort that makes no function calls, and uses no recursion.
const int arrayLength = 40;
float times_array[arrayLength];
float values_array[arrayLength];
// Fill the two arrays....
// Allocate two buffers
float times_buffer[arrayLength];
float values_buffer[arrayLength];
int blockSize = 1;
while (blockSize <= arrayLength)
{
int i = 0;
while (i < arrayLength-blockSize)
{
int begin1 = i;
int end1 = begin1 + blockSize;
int begin2 = end1;
int end2 = begin2 + blockSize;
int bufferIndex = begin1;
while (begin1 < end1 && begin2 < end2)
{
if ( values_array[begin1] > times_array[begin2] )
{
times_buffer[bufferIndex] = times_array[begin2];
values_buffer[bufferIndex++] = values_array[begin2++];
}
else
{
times_buffer[bufferIndex] = times_array[begin1];
values_buffer[bufferIndex++] = values_array[begin1++];
}
}
while ( begin1 < end1 )
{
times_buffer[bufferIndex] = times_array[begin1];
values_buffer[bufferIndex++] = values_array[begin1++];
}
while ( begin2 < end2 )
{
times_buffer[bufferIndex] = times_array[begin2];
values_buffer[bufferIndex++] = values_array[begin2++];
}
for (int k = i; k < i + 2 * blockSize; ++k)
{
times_array[k] = times_buffer[k];
values_array[k] = values_buffer[k];
}
i += 2 * blockSize;
}
blockSize *= 2;
}
I wouldn't suggest writing your own sorting routine, as the sorting routines provided as part of the Java language are well optimized.
The way I'd solve this is to copy the code in the java.util.Arrays class into your own class i.e. org.mydomain.util.Arrays. And add some comments telling yourself not to use the class except when you must have the additional functionality that you're going to add. The Arrays class is quite stable so this is less, less ideal than it would seem, but it's still less than ideal. However, the methods you need to change are private, so you've no real choice.
You then want to create an interface along the lines of:
public static interface SwapHook {
void swap(int a, int b);
}
You then need to add this to the sort method you're going to use, and to every subordinate method called in the sorting procedure, which swaps elements in your primary array. You arrange for the hook to get called by your modified sorting routine, and you can then implement the SortHook interface to achieve the behaviour you want in any secondary (e.g. parallel) arrays.
HTH.