I'm using C++Builder with SuperObject JSON parser, and trying to construct an array.
_di_ISuperObject json = SO("{}");
json->O["data.names"] = SA(ARRAYOFCONST(("")));
for (int i=0; i < v.size(); ++i)
json->A["data.names"]->S[i] = v[i];
Now, the code above does what I want - unless v.size() == 0. In that case, I get an array with a single 'empty' string in it.
This is because of the 'dummy' array creation using ARRAYOFCONST(("")).
What's the correct way to create an 'empty' OPENARRAY to pass to SuperObject?
You cannot use ARRAYOFCONST() or OPENARRAY() to create a 0-element openarray. Those macros require a minimum of 1 input value.
I am not familiar with SuperObject, but if O[] creates a new JSON array from existing values and A[] simply fills the array, you could try using the SLICE() macro to create and fill an openarray from v directly if v is a std::vector<TVarRec>:
if (!v.empty())
json->O["data.names"] = SA( SLICE(&v[0], v.size()) );
If you really need a 0-element openarray if v is empty, try this:
if (v.empty())
json->O["data.names"] = SA( NULL, -1 );
else
json->O["data.names"] = SA( SLICE(&v[0], v.size()) );
If v does not contain TVarRec values then you can create a separate std::vector<TVarRec> first and then SLICE() that into SuperObject (just be careful because TVarRec does not perform reference counting on reference-counted data types, such as strings - by design - so make sure temporaries are not created when you assign the TVarRec values or else they will be leaked!):
if (v.empty())
json->O["data.names"] = SA( NULL, -1 );
else
{
std:vector<TVarRec> tmp(v.size());
for (size_t idx = 0; idx < v.size(); ++idx)
tmp[idx] = v[idx];
json->O["data.names"] = SA( SLICE(&tmp[0], tmp.size()) );
}
Related
I'm experiencing a ClassCastException with the following piece of code.
var temp = set.stream().flatMap(Arrays::stream).toArray(Token[]::new);
I also tried collecting into a set, but I got the same error.
var temp = set.stream().flatMap(Arrays::stream).collect(Collectors.toSet());
set is declared as a Set<Token[]>, but when debugging it says Set<Object[]>.
Edit:
I've narrowed down the issue to the method subsetsWithMinSize. Eventhough I call it with:
new Sets<Token>().subsetsWithMinSize(value, x);
it seems to return a Set<Object[]>. Can someone tell me why that is and how to fix it?
Here is the method subsetsWithMinSize:
public Set<T[]> subsetsWithMinSize(List<T> list, int min) {
Set<T[]> res = new HashSet<>();
for (int i = 0; i <= list.size() - min; i++)
for (int j = 0; list.size() - j >= i + min; j++) {
List<T> temp = new ArrayList<>();
for (int k = i; k < list.size() - j; k++) temp.add(list.get(k));
res.add((T[]) temp.toArray());
}
return res;
}
So after you guys helped me to minimise the search scope I found the issue.
When I was using (T[]) to cast it wouldn't work, because after type erasure T would just be cast to an Object. Here's the thread I found the answer on: How to properly return generic array in Java generic method?.
So to finally correct the code I had to change the method a little by using Array.newInstance() and put in Class<T> to make it work:
public Set<T[]> subsetsWithMinSize(Class<T> clazz, List<T> list, int min) {
Set<T[]> res = new HashSet<>();
for (int i = 0; i <= list.size() - min; i++)
for (int j = 0; list.size() - j >= i + min; j++) {
List<T> temp = new ArrayList<>();
for (int k = i; k < list.size() - j; k++)
temp.add(list.get(k));
var arr = (T[]) Array.newInstance(clazz, temp.size());
IntStream.range(0, temp.size()).forEach(k -> arr[k] = temp.get(k));
res.add(arr);
}
return res;
}
It uses Array.newInstance() to make T[] (cast is still necessary for the compiler) and then just copies temp into that array.
Another option would be to use lists instead of arrays, which is the better way.
Reference from Effective Java:
In Summary, arrays and generics have very different type rules. Arrays are covariant and reified; generics are invariant and erased. As a consequcne, arrays provide runtime type safety but not compile-time type safety and vice versa for generics. Generally speaking, arrays and generics don’t mix well. If you find yourself mixing them and getting compile-time error or warnings, your first impulse should be to replace the arrays with lists.
The issue with that is that, for my use at least, lists use an unnecessarily big amount of space. Combined with the fact that I am making a powerset of the results later everything would just run super slow.
I have a List of the type Model. when I loop all its elements and loop the next one except for the last one, then change the last one manually, the one before changes.
here is a little code to reproduce the problem (also you can run it directly in dartpad from here)
void main() {
List<Model> s = [];
for (int i = 0; i < 5; i++) {
s.add(Model(i));
}
for (int i = 0; i < s.length - 1; i++) {
s[i] = s[i + 1];
}
print(s);
s[s.length-1].x = 100;
print(s);
}
class Model {
int x;
Model(this.x);
#override
String toString() => 'x: ' + this.x.toString();
}
notice that this problem does not happen when you comment out the for loop or the manual change, or instead of changing the last one's property, you reassign a new value to it, like s[s.length - 1] = Model(100);. seems like dart for some reason is re-running the loop.
When you run the second for loop, you assign the i + 1th Model to the ith position in the list:
// initialise list
for (int i = 0; i < s.length; i++) {
s[i] = s[i + 1]
}
If you unwrap the loop, it looks roughly like this:
s[0] = s[1];
s[1] = s[2];
s[2] = s[3];
s[3] = s[4];
Notice that this leaves s[4] unchanged, but also assigns it to s[3].
In Dart, variables contain references to objects. This means that when your list runs s[3] = s[4];, both s[3] and s[4] point to the same object.
Now, if you modify s[4] you, are actually modifying the objects that s[4] refers to, which happens to also be the object that s[3] refers to, so they both appear to change in your list.
Image of my dataset:
I am using the HDF5DotNet with C# and I can read only full data as the attached image in the dataset. The hdf5 file is too big, up to nearly 10GB, and if I load the whole array into the memory then it will be out of memory.
I would like to read all data from rows 5 and 7 in the attached image. Is that anyway to read only these 2 rows data into memory in a time without having to load all data into memory first?
private static void OpenH5File()
{
var h5FileId = H5F.open(#"D:\Sandbox\Flood Modeller\Document\xmdf_results\FMA_T1_10ft_001.xmdf", H5F.OpenMode.ACC_RDONLY);
string dataSetName = "/FMA_T1_10ft_001/Temporal/Depth/Values";
var dataset = H5D.open(h5FileId, dataSetName);
var space = H5D.getSpace(dataset);
var dataType = H5D.getType(dataset);
long[] offset = new long[2];
long[] count = new long[2];
long[] stride = new long[2];
long[] block = new long[2];
offset[0] = 1; // start at row 5
offset[1] = 2; // start at column 0
count[0] = 2; // read 2 rows
count[0] = 165701; // read all columns
stride[0] = 0; // don't skip anything
stride[1] = 0;
block[0] = 1; // blocks are single elements
block[1] = 1;
// Dataspace associated with the dataset in the file
// Select a hyperslab from the file dataspace
H5S.selectHyperslab(space, H5S.SelectOperator.SET, offset, count, block);
// Dimensions of the file dataspace
var dims = H5S.getSimpleExtentDims(space);
// We also need a memory dataspace which is the same size as the file dataspace
var memspace = H5S.create_simple(2, dims);
double[,] dataArray = new double[1, dims[1]]; // just get one array
var wrapArray = new H5Array<double>(dataArray);
// Now we can read the hyperslab
H5D.read(dataset, dataType, memspace, space,
new H5PropertyListId(H5P.Template.DEFAULT), wrapArray);
}
You need to select a hyperslab which has the correct offset, count, stride, and block for the subset of the dataset that you wish to read. These are all arrays which have the same number of dimensions as your dataset.
The block is the size of the element block in each dimension to read, i.e. 1 is a single element.
The offset is the number of blocks from the start of the dataset to start reading, and count is the number of blocks to read.
You can select non-contiguous regions by using stride, which again counts in blocks.
I'm afraid I don't know C#, so the following is in C. In your example, you would have:
hsize_t offset[2], count[2], stride[2], block[2];
offset[0] = 5; // start at row 5
offset[1] = 0; // start at column 0
count[0] = 2; // read 2 rows
count[1] = 165702; // read all columns
stride[0] = 1; // don't skip anything
stride[1] = 1;
block[0] = 1; // blocks are single elements
block[1] = 1;
// This assumes you already have an open dataspace with ID dataspace_id
H5Sselect_hyperslab(dataspace_id, H5S_SELECT_SET, offset, stride, count, block)
You can find more information on reading/writing hyperslabs in the HDF5 tutorial.
It seems there are two forms of H5D.read in C#, you want the second form:
H5D.read(Type) Method (H5DataSetId, H5DataTypeId, H5DataSpaceId,
H5DataSpaceId, H5PropertyListId, H5Array(Type))
This allows you specify the memory and file dataspaces. Essentially, you need one dataspace which has information about the size, stride, offset, etc. of the variable in memory that you want to read into; and one dataspace for the dataset in the file that you want to read from. This lets you do things like read from a non-contiguous region in a file to a contiguous region in an array in memory.
You want something like
// Dataspace associated with the dataset in the file
var dataspace = H5D.get_space(dataset);
// Select a hyperslab from the file dataspace
H5S.selectHyperslab(dataspace, H5S.SelectOperator.SET, offset, count);
// Dimensions of the file dataspace
var dims = H5S.getSimpleExtentDims(dataspace);
// We also need a memory dataspace which is the same size as the file dataspace
var memspace = H5S.create_simple(rank, dims);
// Now we can read the hyperslab
H5D.read(dataset, datatype, memspace, dataspace,
new H5PropertyListId(H5P.Template.DEFAULT), wrapArray);
From your posted code, I think I've spotted the problem. First you do this:
var space = H5D.getSpace(dataset);
then you do
var dataspace = H5D.getSpace(dataset);
These two calls do the same thing, but create two different variables
You call H5S.selectHyperslab with space, but H5D.read uses dataspace.
You need to make sure you are using the correct variables consistently. If you remove the second call to H5D.getSpace, and change dataspace -> space, it should work.
Maybe you want to have a look at HDFql as it abstracts yourself from the low-level details of HDF5. Using HDFql in C#, you can read rows #5 and #7 of dataset Values using a hyperslab selection like this:
float [,]data = new float[2, 165702];
HDFql.Execute("SELECT FROM Values(5:2:2:1) INTO MEMORY " + HDFql.VariableTransientRegister(data));
Afterwards, you can access these rows through variable data. Example:
for(int x = 0; x < 2; x++)
{
for(int y = 0; y < 165702; y++)
{
System.Console.WriteLine(data[x, y]);
}
}
I want to make histogram of my data so, I use histogram class at c# using MathNet.Numerics.Statistics.
double[] array = { 2, 2, 5,56,78,97,3,3,5,23,34,67,12,45,65 };
Vector<double> data = Vector<double>.Build.DenseOfArray(array);
int binAmount = 3;
Histogram _currentHistogram = new Histogram(data, binAmount);
How can I get the count of the biggest bin? Or just the index of the bigest bin? I try to get it by using GetBucketOf but to do this I need the element in this bucket :(
Is there any other way to do this? I read the documentation and Google and I can't find anything.
(Hi, I would use a comment for this but i just joined so today and don't yet have 50 reputation to comment!) I just had a look at - http://numerics.mathdotnet.com/api/MathNet.Numerics.Statistics/Histogram.htm. That documentation page (footer says it was built using http://docu.jagregory.com/) shows a public property named Item which returns a Bucket. I'm wondering if that is the property you need to use because the automatically generated documentation states that the Item property "Gets' the n'th bucket" but isn't clear how the Item property acts as an indexer. Looking at your code i would try _currentHistogram.Item[n] first (if that doesn't work try _currentHistogram[n]) where you are iterating the Buckets in the histogram using something like -
var countOfBiggest = -1;
var indexOfBiggest = -1;
for (var n = 0; n < _currentHistogram.BucketCount; n++)
{
if (_currentHistogram.Item[n].Count > countOfBiggest)
{
countOfBiggest = _currentHistogram.Item[n].Count;
indexOfBiggest = n;
}
}
The code above assumes that Histogram uses 0-based and not 1-based indexing.
Here's part of my JSON:
[
UserJSONImpl{
id=1489761876,
name='CharlesPerin',
screenName='charles_perin',
location='Paris,
France',
description='PhdStudentatINRIA-Univ.Paris-Sud-CNRS-LIMSI#infovis#dataviz#hci',
isContributorsEnabled=false,
profileImageUrl='http: //a0.twimg.com/profile_images/3766400220/bbced44afe69e60eb30e00f593a2f3b5_normal.jpeg',
profileImageUrlHttps='https: //si0.twimg.com/profile_images/3766400220/bbced44afe69e60eb30e00f593a2f3b5_normal.jpeg',
url='http: //t.co/eYSy04EzEk',
isProtected=false,
},
UserJSONImpl{
id=19671465,
name='KevinQuealy',
screenName='KevinQ',
location='NewYork,
NY',
description='AgraphicseditorattheNewYorkTimes.AdjunctatNYU#SHERP.ReturnedPeaceCorpsvolunteer.Bald,
Minnesotan,
talkstoomuch.',
isContributorsEnabled=false,
profileImageUrl='http: //a0.twimg.com/profile_images/2213326305/image_normal.jpg',
profileImageUrlHttps='https: //si0.twimg.com/profile_images/2213326305/image_normal.jpg',
url='http: //t.co/vb0j99kE3N',
isProtected=false,
...(cont)
This was returned directly from a call to twitter4j's lookupUsers:
long[] hundredIDs = new long[100];
org.json.JSONArray users = new org.json.JSONArray();
for(int a = 0; a < (int)((double)friendArray.length()/100 +1); a++)
{
for(int j = 100*a; j < 100*(a+1); j++)
{
hundredIDs[j-100*a] = Long.parseLong(friendArray.getString(j));
}
users = new org.json.JSONArray(twitter.lookupUsers(hundredIDs)); //lookup users in batches of 100
for(int k = 0; k < users.length(); k++)
{
org.json.JSONObject user = users.getJSONObject(k);
if(Long.parseLong(user.getString("followers_count")) >= 500)
{
String id = user.getString("id"); //get id for each JSONObject
friendArrayFiltered.add(id); //store ids in another array
}
}
For some reason, the JSON returned by my code doesn't have the standard quotes around the properties ("id"= ...., rather than id =...). It doesn't seem to be a problem of the Twitter API itself since their examples are in the correct format: https://dev.twitter.com/docs/api/1/get/users/lookup.
Does anyone know what the problem is?
Also, not sure if this is a consequence but when I attempt to access individual elements of the JSONArray (like JSONArray[0]), an error is returned saying JSONArray[0] is not a JSONObject. Is this linked to the above problem?
It's not JSON, it's actually generated by the UserJSONImpl#toString() method which is providing a textual representation for each of the User objects returned by the lookupUsers invocation.
As for your second problem, you cannot use the [] operator on Object types in Java so I'm a little unclear what you mean without further information.
ASIDE
I'm not sure why you are wrapping twitter4j objects in JSONArray and JSONObject objects - of course you may have a good reason for doing this that's not apparent in the question - but you can simply use the methods directly on the returned objects to get the information you need, for example:
final List<User> users = twitter.lookupUsers(hundredIDs);
for (User user : users) {
final int followersCount = user.getFollowersCount();
if (followersCount > 500) {
... etc...
Check out the User JavaDocs and wider documentation for the project.