I have a problem to make data ArrayList whose attributes have ArrayList too. The model data looks like this code.
data class DataArrayInArray02(
val no: Int? = null,
val dataArray: ArrayList<Int>
)
I want to get a data DataArrayInArray02 like this.
This is my code
fun main() {
val dataArrayInArray = ArrayList<DataArrayInArray02>()
val dataChildrenArray = ArrayList<Int>()
for (i in 0..3) {
val data = (0..10).random()
for (j in 0..data) {
val d = (1..1000).random()
dataChildrenArray.add(d)
}
dataArrayInArray.add(DataArrayInArray02(i+1, dataChildrenArray))
println("ID : ${dataArrayInArray[i].no}, Data : ${dataArrayInArray[i].dataArray}")
dataChildrenArray.clear()
}
}
When I run this code, I get the result like the picture above.
I call dataArrayInArray using looping "for" looks like this.
for (j in 0 until dataArrayInArray.size) {
println("ID : ${dataArrayInArray[j].no}, Data : ${dataArrayInArray[j].dataArray}")
}
But, I get the result like this.
So, which code is incorrect? Is it because of using dataChildrenArray.clear()? If I delete that code. The result will get like this:
ID : 1, Data : [915, 565, 591, 254, 67]
ID : 2, Data : [915, 565, 591, 254, 67, 258, 57, 767, 866, 986, 558, 187, 976]
where ID 2 should only display data [258, 57, 767, 866, 986, 558, 187, 976].
How to solve that problem?
You're passing the same instance of an ArrayList<Int> to each instance of DataArrayInArray02 in the top level list. To fix your code, move the line
val dataChildrenArray = ArrayList<Int>()
inside your for loop so a new one is created for each child.
If you're OK with using List instead of ArrayList, you could simplify this:
val dataArrayInArray = (1..4).map { i ->
val innerListSize = (0..10).random()
val innerList = (0..innerListSize).map { (1..1000).random() }
DataArrayInArray02(i, innerList)
}
Related
Is there a concise way to sum the units of the same type of items in a list with Java 8 streams? For example, suppose I have a list of three items:
{id: 10, units: 1}
{id: 20, units: 2}
{id: 10, units: 1}
I like a summary stream like:
{id: 10, units 2}
{id: 20, units 2}
which sums the units of items of the same id. Any ideas?
Here's Federico's solution (with Lombok):
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class So44348207 {
public static void main(String[] args) {
List<Item> items = Arrays.asList(
new Item(10,1), new Item(20,2), new Item(10, 1)
);
Map<Long, Integer> results = items.stream().collect(
Collectors.toMap(
Item::getId,
Item::getUnits,
Integer::sum
)
);
results.forEach( (k,v) -> System.out.println(
String.format("{id: %d, units: %d}", k,v))
);
}
#Data
#AllArgsContructor
public static class Item {
Long id;
Integer units;
}
}
which correctly produces:
java So44348207
{id: 20, units: 2}
{id: 10, units: 2}
Assuming you have a class MyClass that encapsulates both fields and has getters for them, you could do it as follows:
Map<Long, Integer> result = list.stream()
.collect(Collectors.toMap(
MyClass::getId,
MyClass::getUnits,
Integer::sum));
I'm also assuming that id is of type long or Long and units of type int or Integer.
Collectors.toMap creates a map whose keys are determined by its first argument, which is a function that maps an element of the stream to the key of the map. The second argument is a function that maps an element of the stream to the value of the map, and the third argument is an operator that merges two values when there are collisions on the key.
Here is another simple solution by StreamEx
StreamEx.of(items).toMap(Item::getId, Item::getUnits, Integer::sum);
I get a bit confused and frustrated when it comes to using NEST to querying, as it seems very hit and miss. I have no trouble querying when using standard JSON, so I was wondering if there was some way to query using a JSON object, I have code below
var query = "bkala";
var q = new
{
query = new
{
text = new
{
_all = "jane"
}
}
};
var qJson = JsonConvert.SerializeObject(q);
var hits = client.Search<Users>(qJson);
However, I get the error "Cannot convert from type string to System.Func, Nest.ISearchRequest"
If anyone knows how I can simply query using a JSON object, that would be fantastic, cheers in advance.
NEST and Elasticsearch.Net, the low level client that NEST uses under the covers, are flexible in how you wish to query. With NEST you have a couple of different ways:
NEST - High level client
1.Fluent API
var query = "bkala";
var searchResult = client.Search<MyDocument>(s => s
.Query(q => q
.Match(m => m
.Field("_all")
.Query(query)
)
)
);
Laid out as above, this API uses lambda expressions to define a fluent interface that mimics the structure of the Elasticsearch json API and query DSL.
2.Object Initializer Syntax
var query = "bkala";
var request = new SearchRequest<MyDocument>
{
Query = new MatchQuery
{
Field = "_all",
Query = query
}
};
var searchResult = client.Search<MyDocument>(request);
If lambda expressions are not your thing, then you can always define your searches using specific search types.
Elasticsearch.Net - Low level client
In cases where you would like to query with anonymous types (as per your question), json strings or a byte representation of a query, then you can use the low level client, Elasticsearch.Net, to achieve this. The low level client is exposed on the high level client through the .LowLevel property
1.Anonymous types
var query = new
{
query = new
{
match = new
{
_all = new
{
query = "bkala"
}
}
}
};
var searchResult = client.LowLevel.Search<SearchResponse<MyDocument>>(query);
Using the low level client on the high level client means that you can still take advantage of using Json.NET to deserialize search results; in this example, the search response can be accessed through searchResult.Body
2.Json string
var query = #"
{
""query"": {
""match"": {
""_all"": {
""query"": ""bkala""
}
}
}
}";
var searchResult = client.LowLevel.Search<SearchResponse<MyDocument>>(query);
3.Byte array
var bytes = new byte[] { 123, 13, 10, 32, 32, 34, 113, 117, 101, 114, 121, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 34, 109, 97, 116, 99, 104, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 34, 95, 97, 108, 108, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 34, 113, 117, 101, 114, 121, 34, 58, 32, 34, 98, 107, 97, 108, 97, 34, 13, 10, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 125, 13, 10, 32, 32, 125, 13, 10, 125 };
var searchResult = client.LowLevel.Search<SearchResponse<MyDocument>>(bytes);
All of the above methods produce the following query
{
"query": {
"match": {
"_all": {
"query": "bkala"
}
}
}
}
Check out the Getting started guide on the github repo as well as the documentation on the Elastic website. We are continually working to improve documentation and PRs are more than welcome for areas where you feel we are lacking :)
One iPhone is used to transmit ibeacon using locate app (the proximity uuid is 2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6). The android phone is used to detect the ibeacon.
When I debug, I can get the following message:
08-30 15:33:57.051 D/BluetoothLeScanner(27939): onScanResult() - ScanResult{mDevice=6D:CC:9D:8D:3A:F3, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[2, 21, 47, 35, 68, 84, -49, 109, 74, 15, -83, -14, -12, -111, 27, -87, -1, -90, 0, 0, 0, 0, -59]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=null], mRssi=-31, mTimestampNanos=58705755631306}
However in function RangingBeaconsInRegion, there is no beacon.
void RangingBeaconsInRegion(object sender, RangeEventArgs e)
{
await ClearData();
var allBeacons = new List<Beacon>();
if (e.Beacons.Count > 0)
{
foreach (var b in e.Beacons)
{
allBeacons.Add(b);
int rssi = b.Rssi;
System.Diagnostics.Debug.WriteLine(rssi.ToString());
}
var orderedBeacons = allBeacons.OrderBy(b => b.Distance).ToList();
await UpdateData(orderedBeacons);
}
else
{
// unknown
await ClearData();
}
}
The following is my implementation:
public class MainActivity : XFormsApplicationDroid, IBeaconConsumer
{
public MainActivity()
{
}
protected override void OnCreate(Bundle bundle)
{
BeaconManager beaconManager = BeaconManager.GetInstanceForApplication(this);
var iBeaconParser = new BeaconParser();
iBeaconParser.SetBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24");
var parser = new BeaconParser();
parser.SetBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25");
beaconManager.BeaconParsers.Add(parser);
beaconManager.Bind(this);
}
public void OnBeaconServiceConnect()
{
//obtain the beaconservie object of android
var beaconService = Xamarin.Forms.DependencyService.Get<IbeaconService>();
beaconService.InitializeService();
//beaconService.StartTransmitting();
beaconService.StartMonitoring();
beaconService.StartRanging();
}
public void InitializeService()
{
m_beaconManager = InitializeBeaconManager();
}
private BeaconManager InitializeBeaconManager()
{
BeaconManager bm = BeaconManager.GetInstanceForApplication(Xamarin.Forms.Forms.Context);
//set the scan window
bm.SetForegroundScanPeriod(1100L);
//subscribe to the events;
m_monitorNotifier.EnterRegionComplete += EnteredRegion;
m_monitorNotifier.ExitRegionComplete += ExitedRegion;
m_monitorNotifier.DetermineStateForRegionComplete += DeterminedStateForRegionComplete;
m_rangeNotifier.DidRangeBeaconsInRegionComplete += RangingBeaconsInRegion;
// constructs a new region object to be used for ranging or monitoring
m_tagRegion = new Region("myUniqueBeaconId", Identifier.Parse("E4C8A4FC-F68B-470D-959F-29382AF72CE7"), null, null);
m_tagRegion = new Region("myUniqueBeaconId", Identifier.Parse("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), null, null);
m_tagRegion = new Region("myUniqueBeaconId", Identifier.Parse("2F234454-CF6d-4A0F-ADF2-F4911BA9FFA6"), null, null);
m_emptyRegion = new Region("myEmptyBeaconId", null, null, null);
bm.SetBackgroundMode(false);
//
//bm.Bind((IBeaconConsumer)Xamarin.Forms.Forms.Context);
return bm;
}
public void StartRanging()
{
BeaconManagerInstance.SetForegroundBetweenScanPeriod(0L);
m_beaconManager.AddRangeNotifier(m_rangeNotifier);
m_beaconManager.StartRangingBeaconsInRegion(m_tagRegion);
m_beaconManager.StartRangingBeaconsInRegion(m_emptyRegion);
}
If you look closely at the code that sets up the beaconParsers, you'll see that two are constructed, but only one is added like this:
beaconManager.BeaconParsers.Add(parser);
Adding a second call to add the other beacon parser should solve the problem.
Thanks, that's my mistake! After I add a second call to add the other beacon parser! there is still some strange situation: I did not launch any beacon transmitter, but when I debug, I got the following output: D/BluetoothLeScanner( 6864): onScanResult() - ScanResult{mDevice=58:D6:74:3A:34:C5, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={76=[12, 14, 0, 126, 81, 116, -16, 10, 52, 84, 15, 98, 113, 29, -15, 34]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=null], mRssi=-89, mTimestampNanos=122142418198514}
08-31 09:11:13.943 D/BluetoothLeScanner( 6864): onScanResult() - ScanResult{mDevice=58:D6:74:3A:34:C5, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={76=[12, 14, 0, 126, 81, 116, -16, 10, 52, 84, 15, 98, 113, 29, -15, 34]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=null], mRssi=-89, mTimestampNanos=122142560625598}. It seems that one beacon is detected.
I simply want to create a View that uses Map-Reduce to do this: Say I have Documents for the Automobile Industry. I would like the user to query for a particular Make - say Ford for example. I would like the user to provide the Ford value via an EditText, Tap a Button, and the "Count" be shown in a TextView. So, to clarify, I want to do a count of a certain type of Document using Map-Reduce. I have searched for over 100 hundred hours on this and have not found not one single example - REAL example I mean. (I have read all the docs, only generic examples - no actual examples)
I am an experienced programmer 15+ yrs exp - all I need is one example, and I am good to go.
Can someone please assist me with this?
Thanks,
Don
Here is my Actual Code:
string lMS = "MS:5"; // just to show what type of value I am using
var msCount = dbase.GetView ("count_ms");
msCount.SetMapReduce ((doc, emit) => {
if (doc.ContainsKey ("DT") && doc["DT"].Equals ("P")) {
if (doc.ContainsKey ("MS") && doc["MS"].Equals (_ms))
{
emit (doc ["id"], 1);
}
}
},
(keys, values, rereduce) => values.ToList().Count, "1");
var mscView = dbase.GetView ("count_ms");
var query = mscView.CreateQuery ();
query.StartKey = "MS:1";
query.EndKey = "MS:9999";
var queryResults = query.Run ();
var nr = queryResults.Count; // shows a value of 1 - wrong - should be 40
// the line below is to allow me to put a stop statement to read line above
var dummyForStop = nr;
Try setting something like
var docsByMakeCount = _database.GetView("docs_by_make_count");
docsByMakeCount.SetMapReduce((doc, emit) =>
{
if (doc.ContainsKey("Make"))
{
emit(doc["Make"], doc);
}
},
(keys, values, rereduce) => values.ToList().Count
, "1");
when you create your view.
and when you use it:
var docsByMake = _database.GetView("docs_by_make_count");
var query = docsByCity.CreateQuery();
query.StartKey = Make;
query.EndKey = Make;
var queryResults = query.Run();
MessageBox.Show(string.Format("{0} documents has been retrieved for that query", queryResults.Count));
if (queryResults.Count == 0) return;
var documents = queryResults.Select(result => JsonConvert.SerializeObject(result.Value, Formatting.Indented)).ToArray();
var commaSeperaterdDocs = "[" + string.Join(",", documents) + "]";
DocumentText = commaSeperaterdDocs;
In my case Make and DocumentText are properties.
There are some optimizations to be made here, like rereducing, but it's the straight forward way.
I've got a jqGrid where I need to change the model after the data is loaded, but before it's parsed into the grid. In otherwords, I think I want to do it in the loadComplete handler. I see this approach: Setting JqGrid's colName and colModel from JSON data, but I'm have a bunch of grids already written that use the "load data with jqGrid" approach, rather than the "pre-load data and pass it to jqGrid" one used there, and I'm hoping to avoid re-coding, or making this one different.
(Hiding and showing hidden columns isn't practical, either.)
Is this possible?
More details:
Basically, I don't know what columns I need till I see the data. Say I'm showing traffic by state:
Date CA WA NY MN
4/20 100 90 85 72
4/21 95 85 89 70
There's only room to show four states, but there might be many more in the data (or there might be fewer), so I want them listed in order of traffic. Right now, the data is coming in like:
{
date : 4-20,
ca : 100,
wa : 90,
ny : 85,
mn : 72
hi : 56,
il : 30
},
{
date : 4-21,
ca : 95,
wa : 85, // note: for a given row, a column might be relatively lower
ny : 89, // than another. The column order is based on the overall
mn : 70
hi : 60,
il : 45
}
or it could be:
{
date : 4-20,
ny : 110,
hi : 95,
il : 90,
wa : 80
}
I've tried setting up columns like state1, state2, state3, state4 and then using jsonmap to remap them, but it didn't work.
loadonce = true, datatype = json
I found one way which seems work OK.
The idea of my solution is following. You use colModel having many hidden columns with the dummy names like 'cm0', 'cm1', 'cm2', ... All the columns has the same data like you need in your case. To fill the data more easy I use column templates existing since jqGrid 3.8.2:
var mygrid=jQuery("#list"),
cmIntTemplate = {
width:50,
sorttype:"int",
formatter:"integer",
align:"right",
hidden:true
},
cm = [
// here we define the first columns which we always has
// the list can be empty or has some columns with
// the properties other as the rest (without cmIntTemplate)
{name:"date",label:"Date",key:true,width:100, fixed:true,
formatter:'date',formatoptions:{srcformat:"m-d",newformat:"m/d"}}
], maxCol = 30, dummyColumnNamePrefix = "cm";
// Add dummy hidden columns. All the columns has the same template
for (i=0;i<maxCol;i++) {
cm.push({name:dummyColumnNamePrefix+i,template:cmIntTemplate});
}
After that I create jqGrid in the standard way, but with the jsonReader which use the page as function:
jsonReader: {
repeatitems: false,
page: function (obj) {
// ------------------------
// here I add the main code
// ------------------------
return obj.page;
}
}
The function from the jsonReader.page return the same value like as do default jsonReader, but I use the way with function because the function will be called directly before the reading of the main contain of JSON data. Inside of the code I get the first row of the data and use it's property names to fill jsonmap property of the corresponding column and set the column name. Additionally I make some dummy columns needed to display all the JSON data visible and the rest dummy column hidden. The last thing which should be done is correction of the grid width which was calculated previously. So the grid will look like this:
or like this
depend on the JSON input data.
The code of the page function is following:
page: function (obj) {
var rows = obj.rows, colModel = mygrid[0].p.colModel,
cmi, iFirstDummy, firstRow, prop,
orgShrinkToFit, isFound,
showColNames = [], hideColNames = [];
if (typeof(rows) === "undefined" || !$.isArray(rows) || rows.length === 0) {
// something wrong need return
return obj.page;
}
// find the index of the first dummy column
// in the colModel. If we use rownumbers:true,
// multiselect:true or subGrid:true additional
// columns will be inserted at the begining
// of the colModel
iFirstDummy = -1;
for(i=0;i<colModel.length;i++) {
cmi = colModel[i];
if (dummyTestRegex.test(cmi.name)) {
iFirstDummy = i;
break;
}
}
if (iFirstDummy === -1) {
// something wrong need return
return obj.page;
}
orgShrinkToFit = clearShrinkToFit();
// we get the first row of the JSON data
firstRow = rows[0];
for (prop in firstRow) {
if (firstRow.hasOwnProperty(prop)) {
// we will use the properties name of the first row
// as the names of the column headers of the grid
// find column index having prop as the name
isFound = false;
for(i=0;i<colModel.length;i++) {
cmi = colModel[i];
if (cmi.name === prop) {
isFound = true;
showColNames.push(prop);
break;
}
}
if(!isFound) {
// labels defines the column names
cmi = colModel[iFirstDummy];
showColNames.push(cmi.name);
mygrid.jqGrid('setLabel',cmi.name,prop);
// because of bug in jqGrid with calculation of width
// we have to reset the width
cmi.width = cmIntTemplate.width;
// we set jsonmap which jqGrid will use instead
// of dummy column names to read all row data
cmi.jsonmap = prop;
iFirstDummy++;
}
}
}
// fill the list of unused columns
for(i=0;i<colModel.length;i++) {
cmi = colModel[i];
if ($.inArray(cmi.name, showColNames) === -1 && dummyTestRegex.test(cmi.name)) {
hideColNames.push(cmi.name);
}
}
mygrid.jqGrid('showCol',showColNames);
mygrid.jqGrid('hideCol',hideColNames);
setGridWidthAndRestoreShrinkToFit(orgShrinkToFit);
return obj.page;
}
Inside of the page function I use small helper functions
var clearShrinkToFit = function() {
// save the original value of shrinkToFit
var orgShrinkToFit = mygrid.jqGrid('getGridParam','shrinkToFit');
// set shrinkToFit:false to prevent shrinking
// the grid columns after its showing or hiding
mygrid.jqGrid('setGridParam',{shrinkToFit:false});
return orgShrinkToFit;
},
setGridWidthAndRestoreShrinkToFit = function(orgShrinkToFit) {
// calculate the new grid width
var width=0, i=0, headers=mygrid[0].grid.headers, l=headers.length;
for (;i<l; i++) {
var th = headers[i].el;
if (th.style.display !== "none") {
width += $(th).outerWidth();
}
}
// restore the original value of shrinkToFit
mygrid.jqGrid('setGridParam',{shrinkToFit:orgShrinkToFit});
// set the grid width
mygrid.jqGrid('setGridWidth',width);
},
dummyTestRegex = new RegExp(dummyColumnNamePrefix+"(\\d)+");
The working demo you can see here.
UPDATED: Another answer with the demo shows how to create the grid which has another format of input data: [[], [], ...] (array of arrays) - matrix.