问:
How to fix "BoxConstraints forces an infinite width" and how to delete an item from a list?
I am a beginner in Flutter and I can not get the result I want because I have a "layout problem". I tried several things for hours...

Technical problem:

When I click on "add player button" to add a new TextField to set more play name, I have an error: "BoxConstraints forces an infinite width". So, the TextField isn't displayed.

Other features that I do not know how to realize:

- I have a "dropdownmenu' to choose difficulty game. Why the default text isn't displayed (Difficulty: normal)?

- How to do this: When the user clicks on the icon "remove" (see suffixIcon on TextField), then the corresponding fieldText is deleted?

- How to do this: When user click to add player the default HintText is incremented (Player 2, Player 3, Player 4, ....)?
- Why my background gradient doesn't fix when user scroll page? (like in HTML/CSS 'background-attachment: fixed') ?

```<code>import 'package:flutter/material.dart';

/// Styles

///

class Homepage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyHomePageState();
  }
}

class _MyHomePageState extends State<Homepage> {

  String dropdownValue = 'Normal';

  List<TextField> _playerList = new List(); //_playerList is my List name
  int playerListIndex = 0; //Count the number of times "Add" button clicked

  @override
  Widget build(BuildContext context) {
    return Scaffold(

      body: Stack(children: <Widget>[
        // To have a gradient background
        new Container(
          height: MediaQuery.of(context).size.height,
          width: MediaQuery.of(context).size.width,
          decoration: new BoxDecoration(
            gradient: new LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              stops: [0.1, 1],
              colors: [
                Colors.redAccent[200],
                Colors.red[300],
              ],
              tileMode:
                  TileMode.repeated,
            ),
          ),

          //I need SingleChildScrollView to haven't "Overflow yellow bar on bottom screen"
          child: SingleChildScrollView(

            child: Container(

              padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
              child: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  mainAxisSize: MainAxisSize.min,

                  children: <Widget>[
                    // Box to add big image
                    SizedBox(
                      height: 450,
                    ),

                    // DROP DOWN MENU to choose difficulty  modes
                    InputDecorator(
                      decoration: InputDecoration(
                        prefixIcon: const Icon(Icons.games),
                        filled: true,
                      ),
                      child: DropdownButtonHideUnderline(
                        child: new DropdownButton<String>(
                          value: dropdownValue,
                          hint: Text('Difficulty normal'),
                          isDense: true,
                          items: <String>['Normal', 'Easy', 'Hard']
                              .map<DropdownMenuItem<String>>((String value) {
                            return DropdownMenuItem<String>(
                              value: value,
                              child: Text(value),
                            );
                          }).toList(),
                          onChanged: (String newValue) {
                            setState(() {
                              dropdownValue = newValue;
                            });
                          },
                        ),
                      ),
                    ),

                    //Field player name 1. At least I need 1 player
                        new TextField(
                          maxLength: 20,
                          decoration: InputDecoration(
                            prefixIcon: const Icon(Icons.person),
                            filled: true,
                            hintText:"Player 1",
                            counterText: "",
                          ),
                        ),

                    //Field for other player name 2, 3, 4, ...
                    new ListView.builder(
                      padding: EdgeInsets.all(0),
                      shrinkWrap: true,
                      physics: NeverScrollableScrollPhysics(),
                      itemCount: _playerList.length,
                      itemBuilder: (context, index) {
                        TextField widget = _playerList.elementAt(index);
                        return widget;
                      }),

                    //Button to add other field text to set player name. The user can delete a player on click on "clear icon button"
                    new Align(
                      alignment: Alignment.centerRight,
                      child: FlatButton.icon(
                          color: Colors.black,
                          icon: Icon(
                            Icons.add,
                            color: Colors.white,
                            size: 18,
                          ),
                          label: Text('Add player',
                              style:
                                  TextStyle(fontSize: 12, color: Colors.white)),
                          onPressed: () {
                            setState(() {
                              playerListIndex++;
                              _playerList.add(
                                    new TextField(
                                      maxLength: 20,
                                      decoration: InputDecoration(
                                        prefixIcon: const Icon(Icons.person),
                                        suffixIcon: new IconButton(
                                            icon: Icon(Icons.clear),
                                            onPressed: () {
                                              _playerList.removeAt(playerListIndex); //Doesn't work
                                            }),
                                        filled: true,
                                        hintText: "Player $playerListIndex", //Doesn't work i would like Player 2, Player 3, ...
                                        counterText: "",
                                      ),
                                    ),
                              );
                              print(playerListIndex);
                              print(_playerList);
                              print(_playerList[0]);
                            });
                          }),
                    ),
                    new ButtonTheme(
                      minWidth: 350,
                      height: 45,
                      child: FlatButton(
                        color: Colors.black,
                        child: Text('Play',
                            style:
                                TextStyle(fontSize: 18, color: Colors.white)),
                        onPressed: () {
                          // Perform some action
                        },
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ]),
    );
  }

}

</code>```

答:
I think that I understood what's going on. Let's begin:

First. Your TextField is not showing up and you're getting an error because you didn't set a width and a height for it, so, it's trying to get the maximum size as it can get. Solution for this? Wrap it in a Container widget (or SizedBox) and give it a width and a height. That should fix the first problem.

Second. Your DropDownMenu's hint text (Difficulty Normal) is not showing because you're not passing the parameter "hint" in the DropDown widget, See the hint propierty below.

Third. You want to clear the TextField string when click on a suffix, right? To achieve this, pass a GestureDetector or an IconButton as your suffix component, create a TextEditingController and pass it in the TextField, in the controller section, then, on the onPressed/onTap method (depending on which Widget you'll set) set this: _textController.text.clear() method, inside the setState function. This should fix the problem.

Forth. You want the list of player's string to increase as you add more players right? You have many ways to achieve this, one of them is creating an empty list, you can mock to test it, and then, everytime you click the "Add player" button, you'll add a String corresponding to the value inside a for loop passing the for's index as int value in the "Player $index". Again, the for method will receive a setState method, and inside the setState, your logic to add one more Player.

And finally, your gradient does not keep fixed? Hmm, I think you can pass a proprierty in the Scaffold widget called resizeToAvoidBottomInset and set it to false.

If something did not work as you expected, reply it and I'll help you out.

Body:
I am a beginner in Flutter and I can not get the result I want because I have a "layout problem". I tried several things for hours...

Technical problem:

When I click on "add player button" to add a new TextField to set more play name, I have an error: "BoxConstraints forces an infinite width". So, the TextField isn't displayed.

Other features that I do not know how to realize:

- I have a "dropdownmenu' to choose difficulty game. Why the default text isn't displayed (Difficulty: normal)?

- How to do this: When the user clicks on the icon "remove" (see suffixIcon on TextField), then the corresponding fieldText is deleted?

- How to do this: When user click to add player the default HintText is incremented (Player 2, Player 3, Player 4, ....)?
- Why my background gradient doesn't fix when user scroll page? (like in HTML/CSS 'background-attachment: fixed') ?

import 'package:flutter/material.dart';

/// Styles

///

class Homepage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyHomePageState();
  }
}

class _MyHomePageState extends State<Homepage> {

  String dropdownValue = 'Normal';

  List<TextField> _playerList = new List(); //_playerList is my List name
  int playerListIndex = 0; //Count the number of times "Add" button clicked

  @override
  Widget build(BuildContext context) {
    return Scaffold(

      body: Stack(children: <Widget>[
        // To have a gradient background
        new Container(
          height: MediaQuery.of(context).size.height,
          width: MediaQuery.of(context).size.width,
          decoration: new BoxDecoration(
            gradient: new LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              stops: [0.1, 1],
              colors: [
                Colors.redAccent[200],
                Colors.red[300],
              ],
              tileMode:
                  TileMode.repeated,
            ),
          ),

          //I need SingleChildScrollView to haven't "Overflow yellow bar on bottom screen"
          child: SingleChildScrollView(

            child: Container(

              padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
              child: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  mainAxisSize: MainAxisSize.min,

                  children: <Widget>[
                    // Box to add big image
                    SizedBox(
                      height: 450,
                    ),

                    // DROP DOWN MENU to choose difficulty  modes
                    InputDecorator(
                      decoration: InputDecoration(
                        prefixIcon: const Icon(Icons.games),
                        filled: true,
                      ),
                      child: DropdownButtonHideUnderline(
                        child: new DropdownButton<String>(
                          value: dropdownValue,
                          hint: Text('Difficulty normal'),
                          isDense: true,
                          items: <String>['Normal', 'Easy', 'Hard']
                              .map<DropdownMenuItem<String>>((String value) {
                            return DropdownMenuItem<String>(
                              value: value,
                              child: Text(value),
                            );
                          }).toList(),
                          onChanged: (String newValue) {
                            setState(() {
                              dropdownValue = newValue;
                            });
                          },
                        ),
                      ),
                    ),

                    //Field player name 1. At least I need 1 player
                        new TextField(
                          maxLength: 20,
                          decoration: InputDecoration(
                            prefixIcon: const Icon(Icons.person),
                            filled: true,
                            hintText:"Player 1",
                            counterText: "",
                          ),
                        ),

                    //Field for other player name 2, 3, 4, ...
                    new ListView.builder(
                      padding: EdgeInsets.all(0),
                      shrinkWrap: true,
                      physics: NeverScrollableScrollPhysics(),
                      itemCount: _playerList.length,
                      itemBuilder: (context, index) {
                        TextField widget = _playerList.elementAt(index);
                        return widget;
                      }),

                    //Button to add other field text to set player name. The user can delete a player on click on "clear icon button"
                    new Align(
                      alignment: Alignment.centerRight,
                      child: FlatButton.icon(
                          color: Colors.black,
                          icon: Icon(
                            Icons.add,
                            color: Colors.white,
                            size: 18,
                          ),
                          label: Text('Add player',
                              style:
                                  TextStyle(fontSize: 12, color: Colors.white)),
                          onPressed: () {
                            setState(() {
                              playerListIndex++;
                              _playerList.add(
                                    new TextField(
                                      maxLength: 20,
                                      decoration: InputDecoration(
                                        prefixIcon: const Icon(Icons.person),
                                        suffixIcon: new IconButton(
                                            icon: Icon(Icons.clear),
                                            onPressed: () {
                                              _playerList.removeAt(playerListIndex); //Doesn't work
                                            }),
                                        filled: true,
                                        hintText: "Player $playerListIndex", //Doesn't work i would like Player 2, Player 3, ...
                                        counterText: "",
                                      ),
                                    ),
                              );
                              print(playerListIndex);
                              print(_playerList);
                              print(_playerList[0]);
                            });
                          }),
                    ),
                    new ButtonTheme(
                      minWidth: 350,
                      height: 45,
                      child: FlatButton(
                        color: Colors.black,
                        child: Text('Play',
                            style:
                                TextStyle(fontSize: 18, color: Colors.white)),
                        onPressed: () {
                          // Perform some action
                        },
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ]),
    );
  }

}


来源: stackexchange

问:
Django filtering the Q problem when is empty
I have a problem filtering the data and showing the result in a table...

In my template I have some inputs that I send input values with ajax and then i get the value using request.POST.get() in my views. The problem appears when some fields are empty I receive an error "Cannot use None as a query value"

I want to do something like this but i cannot find a solution

ex. when the request.POST.get is empty that Q to be ignored
Can anyone help me?
Thanks and sorry for my english

This is my code in my views.py

```<code>def api(request):
    a = request.POST.get('a')
    b = request.POST.get('b')
    c = request.POST.get('c')
    d = request.POST.get('d')
    e = request.POST.get('e')
    f = request.POST.get('f')
    g = request.POST.get('g')
    h = request.POST.get('h')
    raport = Test.objects.filter(
        Q(data_test__year__gte=a) &
        Q(data_test__year__lte=b) &
        Q(data_in__isnull=c) &
        Q(data_out__isnull=d) &
        Q(adress__fieldone=e) &
        Q(adress__fieldtwo=f) &
        Q(categoru=g) &
        Q(stare=h) &
        Q(medic=i)
    )
    serializer = TestSerializer(raport, many=True)
    return JsonResponse(serializer.data, safe=False)
</code>```

答:
We can make a function that creates a Q-object [Django-doc] for only non-None values, like:

```<code>from django.db.models import Q

def q_without_none(**kwargs):
    return Q(**{k: v for k, v in kwargs.items() <b>if v is not None</b>})</code>```

or if you want to exclude the empty string as well:

```<code>from django.db.models import Q

def <b>q_without_empty</b>(**kwargs):
    return Q(**{k: v for k, v in kwargs.items() <b>if v not in (None, '')</b>})</code>```

Then we can construct the query like:

```<code>raport_pacient = Pacient.objects.filter(
    <b>q_without_none(</b>
        data_creare_pacient__year__gte=de_la,
        data_creare_pacient__year__lte=pana_la,
        data_iesire__isnull=iesit,
        data_deces__isnull=iesit,
        adresa_pacient__judet__nume_judet=judet,
        adresa_pacient__localitate__nume_localitate=localitate,
        categorie=categorie,
        stare_civila=stare_civila,
        medic=request.user.medic
    <b>)</b>
)</code>```

Note: although not really your question, using a JsonResponse with safe=False is, like the name suggests, not very safe. There have been exploits with lists for JSON, so it is usually better to define a dictionary at the top level, for example like:

```<code>return JsonResponse({'data': serializer.data})
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I have a problem filtering the data and showing the result in a table...

In my template I have some inputs that I send input values with ajax and then i get the value using request.POST.get() in my views. The problem appears when some fields are empty I receive an error "Cannot use None as a query value"

I want to do something like this but i cannot find a solution

ex. when the request.POST.get is empty that Q to be ignored
Can anyone help me?
Thanks and sorry for my english

This is my code in my views.py

def api(request):
    a = request.POST.get('a')
    b = request.POST.get('b')
    c = request.POST.get('c')
    d = request.POST.get('d')
    e = request.POST.get('e')
    f = request.POST.get('f')
    g = request.POST.get('g')
    h = request.POST.get('h')
    raport = Test.objects.filter(
        Q(data_test__year__gte=a) &
        Q(data_test__year__lte=b) &
        Q(data_in__isnull=c) &
        Q(data_out__isnull=d) &
        Q(adress__fieldone=e) &
        Q(adress__fieldtwo=f) &
        Q(categoru=g) &
        Q(stare=h) &
        Q(medic=i)
    )
    serializer = TestSerializer(raport, many=True)
    return JsonResponse(serializer.data, safe=False)

Body:
We can make a function that creates a Q-object [Django-doc] for only non-None values, like:

from django.db.models import Q

def q_without_none(**kwargs):
    return Q(**{k: v for k, v in kwargs.items() if v is not None})

or if you want to exclude the empty string as well:

from django.db.models import Q

def q_without_empty(**kwargs):
    return Q(**{k: v for k, v in kwargs.items() if v not in (None, '')})

Then we can construct the query like:

raport_pacient = Pacient.objects.filter(
    q_without_none(
        data_creare_pacient__year__gte=de_la,
        data_creare_pacient__year__lte=pana_la,
        data_iesire__isnull=iesit,
        data_deces__isnull=iesit,
        adresa_pacient__judet__nume_judet=judet,
        adresa_pacient__localitate__nume_localitate=localitate,
        categorie=categorie,
        stare_civila=stare_civila,
        medic=request.user.medic
    )
)

Note: although not really your question, using a JsonResponse with safe=False is, like the name suggests, not very safe. There have been exploits with lists for JSON, so it is usually better to define a dictionary at the top level, for example like:

return JsonResponse({'data': serializer.data})


问:
How to get xml node value based on attribute value c# , asp.net?
how to get xmlnode value based on attribute value in C#.

```<code><Products>
  <Error>0</Error>
  <Product link="OWN">
    <ProductCode>CA</ProductCode>
    <ProductType>Account</ProductType>
    <ProductSubtype>Current Account</ProductSubtype>
    <ProductDescriptionEng>Current Account</ProductDescriptionEng>
    <ProductNumber>1234567</ProductNumber>
    <ProductCurrency></ProductCurrency>
    <ProductCurrencyCode>01</ProductCurrencyCode>
    <ProductBalance>899293.003</ProductBalance>
    <LoanRef></LoanRef>
    <OldLoanRef></OldLoanRef>
    <ProductStandardID>00010001</ProductStandardID>
    <OldLoanRef></OldLoanRef>
    <ProductStatusCode>00</ProductStatusCode>
    <ProductStatus>OPEN</ProductStatus>
    <ProductCategory>Deposit Account</ProductCategory>
  </Product>
</Product>
</code>```

in the above example i would like to get value of Product Link "OWN" based on passing attribute value (1234567)  1234567.

I have tried following code but it doesn't return value "OWN" from 'Product link" node.

```<code>string _accountsXml = GetProducts();
                _xmlDoc.LoadXml(_accountsXml);
                _productLinkType = _xmlDoc.SelectSingleNode(string.Format("//Products[../ProductNumber = '{0}']", prodNumber));
</code>```

答:
You do have to add code to get element's attribute value there, possibly minding the case when the right element was not found. Plus be careful with the element names - both in the xpath expression and in the XML.

The following test code would have "OWN" in the link variable:

```<code>var doc = XDocument.Parse(@"<?xml version=""1.0""?>
<Products>
    <Error>0</Error>
    <Product link=""Global""/>
    <Product link=""OWN"">
        <Some/>
        <ProductNumber>1234567</ProductNumber>
        <Nodes/>
    </Product>
    <Product link=""External"">
        <ProductNumber>777</ProductNumber>
    </Product>
</Products>");

var id = 1234567;
var link = doc
    .XPathSelectElement($"//Product[ProductNumber = '{id}']")
    ?.Attribute("link")
    ?.Value;

Console.WriteLine($"Product link: {link ?? "not found"}");
</code>```

Body:
how to get xmlnode value based on attribute value in C#.

<Products>
  <Error>0</Error>
  <Product link="OWN">
    <ProductCode>CA</ProductCode>
    <ProductType>Account</ProductType>
    <ProductSubtype>Current Account</ProductSubtype>
    <ProductDescriptionEng>Current Account</ProductDescriptionEng>
    <ProductNumber>1234567</ProductNumber>
    <ProductCurrency></ProductCurrency>
    <ProductCurrencyCode>01</ProductCurrencyCode>
    <ProductBalance>899293.003</ProductBalance>
    <LoanRef></LoanRef>
    <OldLoanRef></OldLoanRef>
    <ProductStandardID>00010001</ProductStandardID>
    <OldLoanRef></OldLoanRef>
    <ProductStatusCode>00</ProductStatusCode>
    <ProductStatus>OPEN</ProductStatus>
    <ProductCategory>Deposit Account</ProductCategory>
  </Product>
</Product>

in the above example i would like to get value of Product Link "OWN" based on passing attribute value (1234567)  1234567.

I have tried following code but it doesn't return value "OWN" from 'Product link" node.

string _accountsXml = GetProducts();
                _xmlDoc.LoadXml(_accountsXml);
                _productLinkType = _xmlDoc.SelectSingleNode(string.Format("//Products[../ProductNumber = '{0}']", prodNumber));

Body:
You do have to add code to get element's attribute value there, possibly minding the case when the right element was not found. Plus be careful with the element names - both in the xpath expression and in the XML.

The following test code would have "OWN" in the link variable:

var doc = XDocument.Parse(@"<?xml version=""1.0""?>
<Products>
    <Error>0</Error>
    <Product link=""Global""/>
    <Product link=""OWN"">
        <Some/>
        <ProductNumber>1234567</ProductNumber>
        <Nodes/>
    </Product>
    <Product link=""External"">
        <ProductNumber>777</ProductNumber>
    </Product>
</Products>");

var id = 1234567;
var link = doc
    .XPathSelectElement($"//Product[ProductNumber = '{id}']")
    ?.Attribute("link")
    ?.Value;

Console.WriteLine($"Product link: {link ?? "not found"}");


问:
Given an array of integers, find the first missing positive integer in linear time and constant space
In other words, find the lowest positive integer that does not exist in the array. The array can contain duplicates and negative numbers as well.
This question was asked by Stripe in it's programming interview. I have devised a solution for the same as below:

```<code>#include<bits/stdc++.h>
using namespace std;

int main(){
    int arr[]={1,-1,-5,-3,3,4,2,8};
    int size= sizeof(arr)/sizeof(arr[0]);
    sort(arr, arr+size);
    int min=1;

    for(int i=0; i<size; i++){
        if(arr[i]>min) break;
        if(arr[i]==min) min=min+1;
    }
    cout<<min;
    return 0;
}
</code>```

Here, I am first sorting the array, and then traversing the array once. Before traversing the array, I have initialized a variable named "min" as 1. Now, while traversing the array, when we get an integer that is equal to min, we simply increment the value of min. This ensures that the min variable hold the latest least positive integer that has not occurred yet.
Can you think of any better approach? Thanks in advance.

答:
I didn't test it in detail, but for sorted array here is how I would approach it, any improvements are welcome.
constrains:

linear time

constant space

```<code>solution:
start with lowest positive integer (i.e. lpi <- 1)
while parsing the array, if lpi is already in the array, increment it
</code>```

lpi is now the lowest positive integer not available in the array

simple python function will be as follows:

```<code>def find_lpi(arr):
    lpi = 1
    for i in arr:
        if lpi == i:
            lpi += 1
    return lpi
</code>```

if the array is unsorted, the following could be alternative solution.

first create a binary array, X,  of zeroes with length max(arr).
    For each item in the array mark the index of the X, as 1
    return the smallest index with 0

the following is a simple implementation satisfying

linear time

constant space complexity constraints.

```<code>def find_lpi(arr):
    x = [0 for x in range(max(arr)+1)]
     for i in arr:
         x[i] = 1
     for i in range(1,len(x)):
         if x[i] ==0:
             return i
     return len(x)
</code>```

Body:
In other words, find the lowest positive integer that does not exist in the array. The array can contain duplicates and negative numbers as well.
This question was asked by Stripe in it's programming interview. I have devised a solution for the same as below:

#include<bits/stdc++.h>
using namespace std;

int main(){
    int arr[]={1,-1,-5,-3,3,4,2,8};
    int size= sizeof(arr)/sizeof(arr[0]);
    sort(arr, arr+size);
    int min=1;

    for(int i=0; i<size; i++){
        if(arr[i]>min) break;
        if(arr[i]==min) min=min+1;
    }
    cout<<min;
    return 0;
}

Here, I am first sorting the array, and then traversing the array once. Before traversing the array, I have initialized a variable named "min" as 1. Now, while traversing the array, when we get an integer that is equal to min, we simply increment the value of min. This ensures that the min variable hold the latest least positive integer that has not occurred yet.
Can you think of any better approach? Thanks in advance.

Body:
I didn't test it in detail, but for sorted array here is how I would approach it, any improvements are welcome.
constrains:

linear time

constant space

solution:
start with lowest positive integer (i.e. lpi <- 1)
while parsing the array, if lpi is already in the array, increment it

lpi is now the lowest positive integer not available in the array

simple python function will be as follows:

def find_lpi(arr):
    lpi = 1
    for i in arr:
        if lpi == i:
            lpi += 1
    return lpi

if the array is unsorted, the following could be alternative solution.

first create a binary array, X,  of zeroes with length max(arr).
    For each item in the array mark the index of the X, as 1
    return the smallest index with 0

the following is a simple implementation satisfying

linear time

constant space complexity constraints.

def find_lpi(arr):
    x = [0 for x in range(max(arr)+1)]
     for i in arr:
         x[i] = 1
     for i in range(1,len(x)):
         if x[i] ==0:
             return i
     return len(x)


问:
Laravel whereNotIn plus whereIn doesn't equal total count
How is it possible that whereNotIn() plus whereIn() doesn't equal total count?

Running this:

```<code>$updatedBreeds = [
    86,
    113,
    // etc ....
];

DB::enableQueryLog();

dump(Breed::count());
dump(Breed::whereIn('id', $updatedBreeds)->count());
dump(Breed::whereNotIn('id', $updatedBreeds)->count());

dd(DB::getQueryLog());
</code>```

Returns this:

159

  39

  0

Am I missing something here? The whereNotIn() call should return 120 results.

答:
Apparently, one of the values in the array was null. Which strangely enough led to this behavior.

Here is a dump on $updatedBreeds:

```<code>[
  0 => 86
  1 => 113
- 2 => null // When I removed this value, the whereNotIn() worked
  2 => 44
  3 => 8
  4 => 54
  5 => 54
  // ...
]
</code>```

Body:
How is it possible that whereNotIn() plus whereIn() doesn't equal total count?

Running this:

$updatedBreeds = [
    86,
    113,
    // etc ....
];

DB::enableQueryLog();

dump(Breed::count());
dump(Breed::whereIn('id', $updatedBreeds)->count());
dump(Breed::whereNotIn('id', $updatedBreeds)->count());

dd(DB::getQueryLog());

Returns this:

159

  39

  0

Am I missing something here? The whereNotIn() call should return 120 results.

Body:
Apparently, one of the values in the array was null. Which strangely enough led to this behavior.

Here is a dump on $updatedBreeds:

[
  0 => 86
  1 => 113
- 2 => null // When I removed this value, the whereNotIn() worked
  2 => 44
  3 => 8
  4 => 54
  5 => 54
  // ...
]


问:
Is there an algorithm to figure out a 'nice' number formatting for a sequence of numbers of arbitrary order of magnitude?
I'm currently using an implementation of the Extended Wilkinson Algorithm to generate a sequence of axis tick values. For this, the algorithm is given a value range [min,max] and a number n of desired tick mark values, then it outputs an array of evenly spaced values in the interval [min,max]. What I need to do is, to create String labels from these values, BUT depending on the order of magnitude of these values I would like to switch between scientific notation and decimal notation.

For example for a sequence {0.00001, 0.000015, 0.00002, 0.000025} I would like to use scientific notation {'1.0e-05','1.5e-05','2.0e-05','2.5e-05'}.
For a sequence {0,8,16,24,32} I'd like to display it as decimal notation.
I also don't want unnecessary trailing zeros like 0.001000 or 1.500e-05, but in case of the scientific notation example above, I want one trailing zero when other numbers need to use more decimal places. e.g. '1.00e-05' and '1.05e-05'. But wait there is more, for example for {20.0000001, 20.0000002, 20.0000003} the interesting part is of course the very small deviation of 0.0000001 for each value but 20 is still important, something like '20+1.0e-07' may be desirable because counting the zeros is tedious.
Mixing scientific and decimal in the labels is also not appreciated e.g. {8000, 9000, 1.0e04, 1.1e04} is bad.

The goal is to have a consistent labeling that lets one differentiate between the values and that can be read nicely so that very small or very large values are represented in scientific notation to also save display space.

So the representation to use for a sequence does not depend on the single value itself but the whole sequence has to be taken into account.
Is there a software package available or some research paper that concerns with this matter?

I have tried to implement something myself, but this does not work very well, sometimes it outputs the same strings for different numbers e.g. '86.0001', '86.0001', '86.0002', '86.0002' for {86.0001, 86.00015, 86.0002, 86.00025}.

protected String[] labelsForTicks(double[] ticks){
   String str1 = String.format(Locale.US, "%.4g", ticks[0]);
   String str2 = String.format(Locale.US, "%.4g", ticks[ticks.length-1]);
   String[] labels = new String[ticks.length];
   if(str1.contains("e") || str2.contains("e")){
      for(int i=0; i<ticks.length; i++){
         String l = String.format(Locale.US, "%.4e", ticks[i]);
         String[] Esplit = l.split("e", -2);
         String[] dotsplit = Esplit[0].split("\\.",-2);
         dotsplit[1] = ('#'+dotsplit[1])
               .replaceAll("0", " ")
               .trim()
               .replaceAll(" ", "0")
               .replaceAll("#", "");
         dotsplit[1] = dotsplit[1].isEmpty() ? "0":dotsplit[1];
         l = dotsplit[0]+'.'+dotsplit[1]+'e'+Esplit[1];
         labels[i] = l;
      }
   } else {
      for(int i=0; i<ticks.length; i++){
         String l = String.format(Locale.US, "%.4f", ticks[i]);
         if(l.contains(".")){
            String[] dotsplit = l.split("\\.",-2);
            dotsplit[1] = ('#'+dotsplit[1])
                  .replaceAll("0", " ")
                  .trim()
                  .replaceAll(" ", "0")
                  .replaceAll("#", "");
            if(dotsplit[1].isEmpty()){
               l = dotsplit[0];
            } else {
               l = dotsplit[0]+'.'+dotsplit[1];
            }
         }
         labels[i] = l;
      }
   }
   return labels;
}
```

It tries to decide whether to use scientific or decimal notation using the String format 'g' option on the first and last value in the sequence, and then tries to strip away the unnecessary zeros.

答:
The first problem when receiving the ticks doubles is to round them with the smallest number of digits that make them distinct. This is what the below function ScaleForTicks does. If finds the largest power of 10 that can scale all ticks to integers while keeping them distinct. For ticks >= 0, scaling means dividing by the power of 10, and for ticks < 1, it means multiplying by the power of 10. Once the ticks have been scaled to integer, we round them to 0 decimals. This gives us our base labels. They still require additional processing depending on the power of 10 applied.

The question did not say how many consecutive 0's it is acceptable to have in a label. So, I added the maxZeroDigits parameter to the LabelsForTicks function. So, a label will not be displayed with scientific notation, if it contains maxZeroDigits or less consecutive 0's. Otherwise, scientific notation is used.

Another difficulty is what is illustrated by the ticks 20.0000001 20.0000002 20.0000003 in the question. The problem is to extract the common offset of all labels so as to show the actual small variation 1.0e-07 2.0e-07 3.0e-07. This problem is solved by extracting that common offset from the set of integer labels obtained after scaling. The maxZeroDigits parameter is used to determine whether to format the offset in scientific notation or not.

The question asked for fully formatted labels consisting of an optional offset, a label, and an optional exponent. Because the offset and the exponent are the same for all labels, they can be returned as separate parts. This is what the below LabelsForTicks function does. For n ticks, the first n elements of the returned array are the formatted labels without offset and exponent. The next two elements of the returned array are the label and exponent of the offset. The last element of the returned array is the exponent of the labels. The different parts may be assembled to get fully formatted labels, or they may be used separately, for example to indicate a multiplying factor (x10^2), or an offset (+1.34e+04) for the labels, along the graph axes.

Here is the code.

```<code>static string[] LabelsForTicks(double[] ticks, int maxZeroDigits)
{
    int scale = ScaleForTicks(ticks);

    string[] labels = new string[ticks.Length + 3];

    if (scale >= 0)
    {
        if (scale >= maxZeroDigits + 1)
        {
            for (int i = 0; i < ticks.Length; i++)
                labels[i] = ((long)Math.Round(ticks[i] / Math.Pow(10, scale))).ToString(CultureInfo.InvariantCulture);
        }
        else
        {
            for (int i = 0; i < ticks.Length; i++)
                labels[i] = ((long)ticks[i]).ToString(CultureInfo.InvariantCulture);
        }
    }
    else
    {
        for (int i = 0; i < ticks.Length; i++)
            labels[i] = ((long)Math.Round(ticks[i] * Math.Pow(10, -scale))).ToString(CultureInfo.InvariantCulture);
    }

    // Find common offset.
    char[] mask = labels[0].ToCharArray();
    for (int i = 1; i < ticks.Length; i++)
    {
        for (int j = 0; j < labels[0].Length; j++)
            if (mask[j] != labels[i][j])
                mask[j] = 'x';
    }
    int k = mask.Length - 1;
    while (k >= 0 && mask[k] != 'x') k--;
    for (; k > 0; k--)
    {
        if (!(mask[k] == 'x' || mask[k] != '0'))
        {
            k++;
            break;
        }
    }

    // If there is an offset, and it contains a sequence of more than maxZeroDigits.
    string common = new string(mask, 0, k);
    if (common.Contains(new string('0', maxZeroDigits + 1)))
    {
        // Remove common offset from all labels.
        for (int i = 0; i < ticks.Length; i++)
            labels[i] = labels[i].Substring(k);
        // Add ofsset as the second-to-last label.
        labels[ticks.Length] = common + new string('0', labels[0].Length);
        // Reduce offset.
        string[] offset = LabelForNumber(Convert.ToDouble(labels[ticks.Length]) * Math.Pow(10, scale), maxZeroDigits);
        labels[ticks.Length] = offset[0];
        labels[ticks.Length + 1] = offset[1];
    }

    if (scale < 0)
    {
        int leadingDecimalDigits = (-scale) - labels[0].Length;
        if (leadingDecimalDigits <= maxZeroDigits)
        {
            string zeros = new string('0', leadingDecimalDigits);
            for (int i = 0; i < ticks.Length; i++)
                labels[i] = "0." + zeros + labels[i];
            scale = 0;
        }
        else
        {
            // If only one digit, append "0".
            if (labels[0].Length == 1)
            {
                scale -= 1;
                for (int i = 0; i < ticks.Length; i++)
                    labels[i] = labels[i] + "0";
            }
            // Put decimal point immediately after the first digit.
            scale += labels[0].Length - 1;
            for (int i = 0; i < ticks.Length; i++)
                labels[i] = labels[i][0] + "." + labels[i].Substring(1);
        }
    }
    else if (scale > maxZeroDigits)
    {
        // If only one digit, append "0".
        if (labels[0].Length == 1)
        {
            for (int i = 0; i < ticks.Length; i++)
                labels[i] = labels[i] + "0";
        }
        // Put decimal point immediately after the first digit.
        scale += labels[0].Length - 1;
        for (int i = 0; i < ticks.Length; i++)
            labels[i] = labels[i][0] + "." + labels[i].Substring(1);
    }

    // Add exponent as last labels.
    if (scale < 0 || scale > maxZeroDigits)
    {
        string exponent;
        if (scale < 0)
        {
            exponent = (-scale).ToString();
            if (exponent.Length == 1) exponent = "0" + exponent;
            exponent = "-" + exponent;
        }
        else
        {
            exponent = scale.ToString();
            if (exponent.Length == 1) exponent = "0" + exponent;
            exponent = "+" + exponent;
        }
        labels[ticks.Length + 2] = "e" + exponent;
    }

    return labels;
}

static int ScaleForTicks(double[] ticks)
{
    int scale = -1 + (int)Math.Ceiling(Math.Log10(ticks.Last()));

    int bound = Math.Max(scale - 15, 0);

    while (scale >= bound)
    {
        double t1 = Math.Round(ticks[0] / Math.Pow(10, scale));
        bool success = true;
        for (int i = 1; i < ticks.Length; i++)
        {
            double t2 = Math.Round(ticks[i] / Math.Pow(10, scale));
            if (t1 == t2)
            {
                success = false;
                break;
            }
            t1 = t2;
        }
        if (success)
            return scale;

        scale--;
    }

    bound = Math.Min(-1, scale - 15);

    while (scale >= bound)
    {
        double t1 = Math.Round(ticks[0] * Math.Pow(10, -scale));
        bool success = true;
        for (int i = 1; i < ticks.Length; i++)
        {
            double t2 = Math.Round(ticks[i] * Math.Pow(10, -scale));
            if (t1 == t2)
            {
                success = false;
                break;
            }
            t1 = t2;
        }
        if (success)
            return scale;

        scale--;
    }

    return scale;
}

static string[] LabelForNumber(double number, int maxZeroDigits)
{
    int scale = ScaleNumber(number);

    string[] labels = new string[2];

    if (scale >= 0)
    {
        if (scale >= maxZeroDigits + 1)
            labels[0] = ((long)Math.Round(number / Math.Pow(10, scale))).ToString(CultureInfo.InvariantCulture);
        else
            labels[0] = ((long)number).ToString(CultureInfo.InvariantCulture);
    }
    else
    {
        labels[0] = ((long)Math.Round(number * Math.Pow(10, -scale))).ToString(CultureInfo.InvariantCulture);
    }

    if (scale < 0)
    {
        int leadingDecimalDigits = (-scale) - labels[0].Length;
        if (leadingDecimalDigits <= maxZeroDigits)
        {
            string zeros = new string('0', leadingDecimalDigits);
            labels[0] = "0." + zeros + labels[0].TrimEnd(new char[] { '0' });
            scale = 0;
        }
        else
        {
            // Put decimal point immediately after the first digit.
            scale += labels[0].Length - 1;
            labels[0] = labels[0][0] + "." + labels[0].Substring(1);
            labels[0] = labels[0].TrimEnd(new char[] { '0' });
            // If only one digit, append "0".
            if (labels[0].Length == 2)
                labels[0] = labels[0] + "0";
        }
    }
    else if (scale > maxZeroDigits)
    {
        // Put decimal point immediately after the first digit.
        scale -= labels[0].Length - 1;
        labels[0] = labels[0][0] + "." + labels[0].Substring(1);
        labels[0] = labels[0].TrimEnd(new char[] { '0' });
        // If only one digit, append "0".
        if (labels[0].Length == 2)
            labels[0] = labels[0] + "0";
    }

    // Add exponent as last labels.
    if (scale < 0 || scale > maxZeroDigits)
    {
        string exponent;
        if (scale < 0)
        {
            exponent = (-scale).ToString();
            if (exponent.Length == 1) exponent = "0" + exponent;
            exponent = "-" + exponent;
        }
        else
        {
            exponent = scale.ToString();
            if (exponent.Length == 1) exponent = "0" + exponent;
            exponent = "+" + exponent;
        }
        labels[1] = "e" + exponent;
    }

    return labels;
}

static int ScaleNumber(double number)
{
    int scale = (int)Math.Ceiling(Math.Log10(number));

    int bound = Math.Max(scale - 15, 0);

    while (scale >= bound)
    {
        if (Math.Round(number / Math.Pow(10, scale)) == number / Math.Pow(10, scale))
            return scale;
        scale--;
    }

    bound = Math.Min(-1, scale - 15);

    while (scale >= bound)
    {
        if (Math.Round(number * Math.Pow(10, -scale)) == number * Math.Pow(10, -scale))
            return scale;
        scale--;
    }

    return scale;
}
</code>```

Here are several examples with maxZeroDigits set to 3 and 2.

```<code>Ticks: 1 2 3 4
MaxZeroDigits: 3
Labels: 1 2 3 4
Exponent:
Offset:

Ticks: 10 11 12 13
MaxZeroDigits: 3
Labels: 10 11 12 13
Exponent:
Offset:

Ticks: 100 110 120 130
MaxZeroDigits: 3
Labels: 100 110 120 130
Exponent:
Offset:

Ticks: 1000 1100 1200 1300
MaxZeroDigits: 3
Labels: 1000 1100 1200 1300
Exponent:
Offset:

Ticks: 10000 11000 12000 13000
MaxZeroDigits: 3
Labels: 10000 11000 12000 13000
Exponent:
Offset:

Ticks: 100000 110000 120000 130000
MaxZeroDigits: 3
Labels: 1.0 1.1 1.2 1.3
Exponent: e+05
Offset:

Ticks: 1.8E+15 1.9E+15 2E+15 2.1E+15
MaxZeroDigits: 3
Labels: 1.8 1.9 2.0 2.1
Exponent: e+15
Offset:

Ticks: 1.8E+35 1.9E+35 2E+35 2.1E+35
MaxZeroDigits: 3
Labels: 1.8 1.9 2.0 2.1
Exponent: e+35
Offset:

Ticks: 2000.000001 2000.0000015 2000.000002 2000.0000025
MaxZeroDigits: 3
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset: 2000

Ticks: 20000.00000105 20000.0000011 20000.00000115 20000.0000012
MaxZeroDigits: 3
Labels: 1.05 1.10 1.15 1.20
Exponent: e-06
Offset: 2.0e+04

Ticks: 2.000001 2.000002 2.000003 2.000004
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 2

Ticks: 20.000001 20.000002 20.000003 20.000004
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 20

Ticks: 200.000001 200.0000015 200.000002 200.0000025
MaxZeroDigits: 3
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset: 200

Ticks: 200000.000001 200000.000002 200000.000003 200000.000004
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 2.0e+05

Ticks: 2.0000001E+35 2.0000002E+35 2.0000003E+35 2.0000004E+35
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e+29
Offset: 2.0e+35

Ticks: 0.1 0.15 0.2 0.25
MaxZeroDigits: 3
Labels: 0.10 0.15 0.20 0.25
Exponent:
Offset:

Ticks: 0.01 0.015 0.02 0.025
MaxZeroDigits: 3
Labels: 0.010 0.015 0.020 0.025
Exponent:
Offset:

Ticks: 0.001 0.0015 0.002 0.0025
MaxZeroDigits: 3
Labels: 0.0010 0.0015 0.0020 0.0025
Exponent:
Offset:

Ticks: 0.0001 0.00015 0.0002 0.00025
MaxZeroDigits: 3
Labels: 0.00010 0.00015 0.00020 0.00025
Exponent:
Offset:

Ticks: 1E-05 1.5E-05 2E-05 2.5E-05
MaxZeroDigits: 3
Labels: 1.0 1.5 2.0 2.5
Exponent: e-05
Offset:

Ticks: 1E-06 1.5E-06 2E-06 2.5E-06
MaxZeroDigits: 3
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset:

Ticks: 1.8E-13 1.9E-13 2E-13 2.1E-13
MaxZeroDigits: 3
Labels: 1.8 1.9 2.0 2.1
Exponent: e-13
Offset:

Ticks: 1.8E-33 1.9E-33 2E-33 2.1E-33
MaxZeroDigits: 3
Labels: 1.8 1.9 2.0 2.1
Exponent: e-33
Offset:

Ticks: 2.0000001E-33 2.0000002E-33 2.0000003E-33 2.0000004E-33
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e-40
Offset: 2.0e-33

Ticks: 2.00000000015E-30 2.0000000002E-30 2.00000000025E-30 2.0000000003E-30
MaxZeroDigits: 3
Labels: 1.5 2.0 2.5 3.0
Exponent: e-40
Offset: 2.0e-30

Ticks: 0.0010000010001 0.0010000010002 0.0010000010003 0.0010000010004
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e-13
Offset: 0.001000001

Ticks: 0.0010000010001 0.00100000100015 0.0010000010002 0.00100000100025
MaxZeroDigits: 3
Labels: 1.0 1.5 2.0 2.5
Exponent: e-13
Offset: 0.001000001

Ticks: 1000001000.1 1000001000.2 1000001000.3 1000001000.4
MaxZeroDigits: 3
Labels: 0.1 0.2 0.3 0.4
Exponent:
Offset: 1000001000

Ticks: 1 2 3 4
MaxZeroDigits: 2
Labels: 1 2 3 4
Exponent:
Offset:

Ticks: 10 11 12 13
MaxZeroDigits: 2
Labels: 10 11 12 13
Exponent:
Offset:

Ticks: 100 110 120 130
MaxZeroDigits: 2
Labels: 100 110 120 130
Exponent:
Offset:

Ticks: 1000 1100 1200 1300
MaxZeroDigits: 2
Labels: 1000 1100 1200 1300
Exponent:
Offset:

Ticks: 10000 11000 12000 13000
MaxZeroDigits: 2
Labels: 1.0 1.1 1.2 1.3
Exponent: e+04
Offset:

Ticks: 100000 110000 120000 130000
MaxZeroDigits: 2
Labels: 1.0 1.1 1.2 1.3
Exponent: e+05
Offset:

Ticks: 1.8E+15 1.9E+15 2E+15 2.1E+15
MaxZeroDigits: 2
Labels: 1.8 1.9 2.0 2.1
Exponent: e+15
Offset:

Ticks: 1.8E+35 1.9E+35 2E+35 2.1E+35
MaxZeroDigits: 2
Labels: 1.8 1.9 2.0 2.1
Exponent: e+35
Offset:

Ticks: 2000.000001 2000.0000015 2000.000002 2000.0000025
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset: 2.0e+03

Ticks: 20000.00000105 20000.0000011 20000.00000115 20000.0000012
MaxZeroDigits: 2
Labels: 1.05 1.10 1.15 1.20
Exponent: e-06
Offset: 2.0e+04

Ticks: 2.000001 2.000002 2.000003 2.000004
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 2

Ticks: 20.000001 20.000002 20.000003 20.000004
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 20

Ticks: 200.000001 200.0000015 200.000002 200.0000025
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset: 200

Ticks: 200000.000001 200000.000002 200000.000003 200000.000004
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 2.0e+05

Ticks: 2.0000001E+35 2.0000002E+35 2.0000003E+35 2.0000004E+35
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e+29
Offset: 2.0e+35

Ticks: 0.1 0.15 0.2 0.25
MaxZeroDigits: 2
Labels: 0.10 0.15 0.20 0.25
Exponent:
Offset:

Ticks: 0.01 0.015 0.02 0.025
MaxZeroDigits: 2
Labels: 0.010 0.015 0.020 0.025
Exponent:
Offset:

Ticks: 0.001 0.0015 0.002 0.0025
MaxZeroDigits: 2
Labels: 0.0010 0.0015 0.0020 0.0025
Exponent:
Offset:

Ticks: 0.0001 0.00015 0.0002 0.00025
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-04
Offset:

Ticks: 1E-05 1.5E-05 2E-05 2.5E-05
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-05
Offset:

Ticks: 1E-06 1.5E-06 2E-06 2.5E-06
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset:

Ticks: 1.8E-13 1.9E-13 2E-13 2.1E-13
MaxZeroDigits: 2
Labels: 1.8 1.9 2.0 2.1
Exponent: e-13
Offset:

Ticks: 1.8E-33 1.9E-33 2E-33 2.1E-33
MaxZeroDigits: 2
Labels: 1.8 1.9 2.0 2.1
Exponent: e-33
Offset:

Ticks: 2.0000001E-33 2.0000002E-33 2.0000003E-33 2.0000004E-33
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e-40
Offset: 2.0e-33

Ticks: 2.00000000015E-30 2.0000000002E-30 2.00000000025E-30 2.0000000003E-30
MaxZeroDigits: 2
Labels: 1.5 2.0 2.5 3.0
Exponent: e-40
Offset: 2.0e-30

Ticks: 0.0010000010001 0.0010000010002 0.0010000010003 0.0010000010004
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e-13
Offset: 0.001000001

Ticks: 0.0010000010001 0.00100000100015 0.0010000010002 0.00100000100025
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-13
Offset: 0.001000001

Ticks: 1000001000.1 1000001000.2 1000001000.3 1000001000.4
MaxZeroDigits: 2
Labels: 0.1 0.2 0.3 0.4
Exponent:
Offset: 1.000001e-03
</code>```

Body:
I'm currently using an implementation of the Extended Wilkinson Algorithm to generate a sequence of axis tick values. For this, the algorithm is given a value range [min,max] and a number n of desired tick mark values, then it outputs an array of evenly spaced values in the interval [min,max]. What I need to do is, to create String labels from these values, BUT depending on the order of magnitude of these values I would like to switch between scientific notation and decimal notation.

For example for a sequence {0.00001, 0.000015, 0.00002, 0.000025} I would like to use scientific notation {'1.0e-05','1.5e-05','2.0e-05','2.5e-05'}.
For a sequence {0,8,16,24,32} I'd like to display it as decimal notation.
I also don't want unnecessary trailing zeros like 0.001000 or 1.500e-05, but in case of the scientific notation example above, I want one trailing zero when other numbers need to use more decimal places. e.g. '1.00e-05' and '1.05e-05'. But wait there is more, for example for {20.0000001, 20.0000002, 20.0000003} the interesting part is of course the very small deviation of 0.0000001 for each value but 20 is still important, something like '20+1.0e-07' may be desirable because counting the zeros is tedious.
Mixing scientific and decimal in the labels is also not appreciated e.g. {8000, 9000, 1.0e04, 1.1e04} is bad.

The goal is to have a consistent labeling that lets one differentiate between the values and that can be read nicely so that very small or very large values are represented in scientific notation to also save display space.

So the representation to use for a sequence does not depend on the single value itself but the whole sequence has to be taken into account.
Is there a software package available or some research paper that concerns with this matter?

I have tried to implement something myself, but this does not work very well, sometimes it outputs the same strings for different numbers e.g. '86.0001', '86.0001', '86.0002', '86.0002' for {86.0001, 86.00015, 86.0002, 86.00025}.

protected String[] labelsForTicks(double[] ticks){
   String str1 = String.format(Locale.US, "%.4g", ticks[0]);
   String str2 = String.format(Locale.US, "%.4g", ticks[ticks.length-1]);
   String[] labels = new String[ticks.length];
   if(str1.contains("e") || str2.contains("e")){
      for(int i=0; i<ticks.length; i++){
         String l = String.format(Locale.US, "%.4e", ticks[i]);
         String[] Esplit = l.split("e", -2);
         String[] dotsplit = Esplit[0].split("\\.",-2);
         dotsplit[1] = ('#'+dotsplit[1])
               .replaceAll("0", " ")
               .trim()
               .replaceAll(" ", "0")
               .replaceAll("#", "");
         dotsplit[1] = dotsplit[1].isEmpty() ? "0":dotsplit[1];
         l = dotsplit[0]+'.'+dotsplit[1]+'e'+Esplit[1];
         labels[i] = l;
      }
   } else {
      for(int i=0; i<ticks.length; i++){
         String l = String.format(Locale.US, "%.4f", ticks[i]);
         if(l.contains(".")){
            String[] dotsplit = l.split("\\.",-2);
            dotsplit[1] = ('#'+dotsplit[1])
                  .replaceAll("0", " ")
                  .trim()
                  .replaceAll(" ", "0")
                  .replaceAll("#", "");
            if(dotsplit[1].isEmpty()){
               l = dotsplit[0];
            } else {
               l = dotsplit[0]+'.'+dotsplit[1];
            }
         }
         labels[i] = l;
      }
   }
   return labels;
}

It tries to decide whether to use scientific or decimal notation using the String format 'g' option on the first and last value in the sequence, and then tries to strip away the unnecessary zeros.

Body:
The first problem when receiving the ticks doubles is to round them with the smallest number of digits that make them distinct. This is what the below function ScaleForTicks does. If finds the largest power of 10 that can scale all ticks to integers while keeping them distinct. For ticks >= 0, scaling means dividing by the power of 10, and for ticks < 1, it means multiplying by the power of 10. Once the ticks have been scaled to integer, we round them to 0 decimals. This gives us our base labels. They still require additional processing depending on the power of 10 applied.

The question did not say how many consecutive 0's it is acceptable to have in a label. So, I added the maxZeroDigits parameter to the LabelsForTicks function. So, a label will not be displayed with scientific notation, if it contains maxZeroDigits or less consecutive 0's. Otherwise, scientific notation is used.

Another difficulty is what is illustrated by the ticks 20.0000001 20.0000002 20.0000003 in the question. The problem is to extract the common offset of all labels so as to show the actual small variation 1.0e-07 2.0e-07 3.0e-07. This problem is solved by extracting that common offset from the set of integer labels obtained after scaling. The maxZeroDigits parameter is used to determine whether to format the offset in scientific notation or not.

The question asked for fully formatted labels consisting of an optional offset, a label, and an optional exponent. Because the offset and the exponent are the same for all labels, they can be returned as separate parts. This is what the below LabelsForTicks function does. For n ticks, the first n elements of the returned array are the formatted labels without offset and exponent. The next two elements of the returned array are the label and exponent of the offset. The last element of the returned array is the exponent of the labels. The different parts may be assembled to get fully formatted labels, or they may be used separately, for example to indicate a multiplying factor (x10^2), or an offset (+1.34e+04) for the labels, along the graph axes.

Here is the code.

static string[] LabelsForTicks(double[] ticks, int maxZeroDigits)
{
    int scale = ScaleForTicks(ticks);

    string[] labels = new string[ticks.Length + 3];

    if (scale >= 0)
    {
        if (scale >= maxZeroDigits + 1)
        {
            for (int i = 0; i < ticks.Length; i++)
                labels[i] = ((long)Math.Round(ticks[i] / Math.Pow(10, scale))).ToString(CultureInfo.InvariantCulture);
        }
        else
        {
            for (int i = 0; i < ticks.Length; i++)
                labels[i] = ((long)ticks[i]).ToString(CultureInfo.InvariantCulture);
        }
    }
    else
    {
        for (int i = 0; i < ticks.Length; i++)
            labels[i] = ((long)Math.Round(ticks[i] * Math.Pow(10, -scale))).ToString(CultureInfo.InvariantCulture);
    }

    // Find common offset.
    char[] mask = labels[0].ToCharArray();
    for (int i = 1; i < ticks.Length; i++)
    {
        for (int j = 0; j < labels[0].Length; j++)
            if (mask[j] != labels[i][j])
                mask[j] = 'x';
    }
    int k = mask.Length - 1;
    while (k >= 0 && mask[k] != 'x') k--;
    for (; k > 0; k--)
    {
        if (!(mask[k] == 'x' || mask[k] != '0'))
        {
            k++;
            break;
        }
    }

    // If there is an offset, and it contains a sequence of more than maxZeroDigits.
    string common = new string(mask, 0, k);
    if (common.Contains(new string('0', maxZeroDigits + 1)))
    {
        // Remove common offset from all labels.
        for (int i = 0; i < ticks.Length; i++)
            labels[i] = labels[i].Substring(k);
        // Add ofsset as the second-to-last label.
        labels[ticks.Length] = common + new string('0', labels[0].Length);
        // Reduce offset.
        string[] offset = LabelForNumber(Convert.ToDouble(labels[ticks.Length]) * Math.Pow(10, scale), maxZeroDigits);
        labels[ticks.Length] = offset[0];
        labels[ticks.Length + 1] = offset[1];
    }

    if (scale < 0)
    {
        int leadingDecimalDigits = (-scale) - labels[0].Length;
        if (leadingDecimalDigits <= maxZeroDigits)
        {
            string zeros = new string('0', leadingDecimalDigits);
            for (int i = 0; i < ticks.Length; i++)
                labels[i] = "0." + zeros + labels[i];
            scale = 0;
        }
        else
        {
            // If only one digit, append "0".
            if (labels[0].Length == 1)
            {
                scale -= 1;
                for (int i = 0; i < ticks.Length; i++)
                    labels[i] = labels[i] + "0";
            }
            // Put decimal point immediately after the first digit.
            scale += labels[0].Length - 1;
            for (int i = 0; i < ticks.Length; i++)
                labels[i] = labels[i][0] + "." + labels[i].Substring(1);
        }
    }
    else if (scale > maxZeroDigits)
    {
        // If only one digit, append "0".
        if (labels[0].Length == 1)
        {
            for (int i = 0; i < ticks.Length; i++)
                labels[i] = labels[i] + "0";
        }
        // Put decimal point immediately after the first digit.
        scale += labels[0].Length - 1;
        for (int i = 0; i < ticks.Length; i++)
            labels[i] = labels[i][0] + "." + labels[i].Substring(1);
    }

    // Add exponent as last labels.
    if (scale < 0 || scale > maxZeroDigits)
    {
        string exponent;
        if (scale < 0)
        {
            exponent = (-scale).ToString();
            if (exponent.Length == 1) exponent = "0" + exponent;
            exponent = "-" + exponent;
        }
        else
        {
            exponent = scale.ToString();
            if (exponent.Length == 1) exponent = "0" + exponent;
            exponent = "+" + exponent;
        }
        labels[ticks.Length + 2] = "e" + exponent;
    }

    return labels;
}

static int ScaleForTicks(double[] ticks)
{
    int scale = -1 + (int)Math.Ceiling(Math.Log10(ticks.Last()));

    int bound = Math.Max(scale - 15, 0);

    while (scale >= bound)
    {
        double t1 = Math.Round(ticks[0] / Math.Pow(10, scale));
        bool success = true;
        for (int i = 1; i < ticks.Length; i++)
        {
            double t2 = Math.Round(ticks[i] / Math.Pow(10, scale));
            if (t1 == t2)
            {
                success = false;
                break;
            }
            t1 = t2;
        }
        if (success)
            return scale;

        scale--;
    }

    bound = Math.Min(-1, scale - 15);

    while (scale >= bound)
    {
        double t1 = Math.Round(ticks[0] * Math.Pow(10, -scale));
        bool success = true;
        for (int i = 1; i < ticks.Length; i++)
        {
            double t2 = Math.Round(ticks[i] * Math.Pow(10, -scale));
            if (t1 == t2)
            {
                success = false;
                break;
            }
            t1 = t2;
        }
        if (success)
            return scale;

        scale--;
    }

    return scale;
}

static string[] LabelForNumber(double number, int maxZeroDigits)
{
    int scale = ScaleNumber(number);

    string[] labels = new string[2];

    if (scale >= 0)
    {
        if (scale >= maxZeroDigits + 1)
            labels[0] = ((long)Math.Round(number / Math.Pow(10, scale))).ToString(CultureInfo.InvariantCulture);
        else
            labels[0] = ((long)number).ToString(CultureInfo.InvariantCulture);
    }
    else
    {
        labels[0] = ((long)Math.Round(number * Math.Pow(10, -scale))).ToString(CultureInfo.InvariantCulture);
    }

    if (scale < 0)
    {
        int leadingDecimalDigits = (-scale) - labels[0].Length;
        if (leadingDecimalDigits <= maxZeroDigits)
        {
            string zeros = new string('0', leadingDecimalDigits);
            labels[0] = "0." + zeros + labels[0].TrimEnd(new char[] { '0' });
            scale = 0;
        }
        else
        {
            // Put decimal point immediately after the first digit.
            scale += labels[0].Length - 1;
            labels[0] = labels[0][0] + "." + labels[0].Substring(1);
            labels[0] = labels[0].TrimEnd(new char[] { '0' });
            // If only one digit, append "0".
            if (labels[0].Length == 2)
                labels[0] = labels[0] + "0";
        }
    }
    else if (scale > maxZeroDigits)
    {
        // Put decimal point immediately after the first digit.
        scale -= labels[0].Length - 1;
        labels[0] = labels[0][0] + "." + labels[0].Substring(1);
        labels[0] = labels[0].TrimEnd(new char[] { '0' });
        // If only one digit, append "0".
        if (labels[0].Length == 2)
            labels[0] = labels[0] + "0";
    }

    // Add exponent as last labels.
    if (scale < 0 || scale > maxZeroDigits)
    {
        string exponent;
        if (scale < 0)
        {
            exponent = (-scale).ToString();
            if (exponent.Length == 1) exponent = "0" + exponent;
            exponent = "-" + exponent;
        }
        else
        {
            exponent = scale.ToString();
            if (exponent.Length == 1) exponent = "0" + exponent;
            exponent = "+" + exponent;
        }
        labels[1] = "e" + exponent;
    }

    return labels;
}

static int ScaleNumber(double number)
{
    int scale = (int)Math.Ceiling(Math.Log10(number));

    int bound = Math.Max(scale - 15, 0);

    while (scale >= bound)
    {
        if (Math.Round(number / Math.Pow(10, scale)) == number / Math.Pow(10, scale))
            return scale;
        scale--;
    }

    bound = Math.Min(-1, scale - 15);

    while (scale >= bound)
    {
        if (Math.Round(number * Math.Pow(10, -scale)) == number * Math.Pow(10, -scale))
            return scale;
        scale--;
    }

    return scale;
}

Here are several examples with maxZeroDigits set to 3 and 2.

Ticks: 1 2 3 4
MaxZeroDigits: 3
Labels: 1 2 3 4
Exponent:
Offset:

Ticks: 10 11 12 13
MaxZeroDigits: 3
Labels: 10 11 12 13
Exponent:
Offset:

Ticks: 100 110 120 130
MaxZeroDigits: 3
Labels: 100 110 120 130
Exponent:
Offset:

Ticks: 1000 1100 1200 1300
MaxZeroDigits: 3
Labels: 1000 1100 1200 1300
Exponent:
Offset:

Ticks: 10000 11000 12000 13000
MaxZeroDigits: 3
Labels: 10000 11000 12000 13000
Exponent:
Offset:

Ticks: 100000 110000 120000 130000
MaxZeroDigits: 3
Labels: 1.0 1.1 1.2 1.3
Exponent: e+05
Offset:

Ticks: 1.8E+15 1.9E+15 2E+15 2.1E+15
MaxZeroDigits: 3
Labels: 1.8 1.9 2.0 2.1
Exponent: e+15
Offset:

Ticks: 1.8E+35 1.9E+35 2E+35 2.1E+35
MaxZeroDigits: 3
Labels: 1.8 1.9 2.0 2.1
Exponent: e+35
Offset:

Ticks: 2000.000001 2000.0000015 2000.000002 2000.0000025
MaxZeroDigits: 3
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset: 2000

Ticks: 20000.00000105 20000.0000011 20000.00000115 20000.0000012
MaxZeroDigits: 3
Labels: 1.05 1.10 1.15 1.20
Exponent: e-06
Offset: 2.0e+04

Ticks: 2.000001 2.000002 2.000003 2.000004
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 2

Ticks: 20.000001 20.000002 20.000003 20.000004
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 20

Ticks: 200.000001 200.0000015 200.000002 200.0000025
MaxZeroDigits: 3
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset: 200

Ticks: 200000.000001 200000.000002 200000.000003 200000.000004
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 2.0e+05

Ticks: 2.0000001E+35 2.0000002E+35 2.0000003E+35 2.0000004E+35
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e+29
Offset: 2.0e+35

Ticks: 0.1 0.15 0.2 0.25
MaxZeroDigits: 3
Labels: 0.10 0.15 0.20 0.25
Exponent:
Offset:

Ticks: 0.01 0.015 0.02 0.025
MaxZeroDigits: 3
Labels: 0.010 0.015 0.020 0.025
Exponent:
Offset:

Ticks: 0.001 0.0015 0.002 0.0025
MaxZeroDigits: 3
Labels: 0.0010 0.0015 0.0020 0.0025
Exponent:
Offset:

Ticks: 0.0001 0.00015 0.0002 0.00025
MaxZeroDigits: 3
Labels: 0.00010 0.00015 0.00020 0.00025
Exponent:
Offset:

Ticks: 1E-05 1.5E-05 2E-05 2.5E-05
MaxZeroDigits: 3
Labels: 1.0 1.5 2.0 2.5
Exponent: e-05
Offset:

Ticks: 1E-06 1.5E-06 2E-06 2.5E-06
MaxZeroDigits: 3
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset:

Ticks: 1.8E-13 1.9E-13 2E-13 2.1E-13
MaxZeroDigits: 3
Labels: 1.8 1.9 2.0 2.1
Exponent: e-13
Offset:

Ticks: 1.8E-33 1.9E-33 2E-33 2.1E-33
MaxZeroDigits: 3
Labels: 1.8 1.9 2.0 2.1
Exponent: e-33
Offset:

Ticks: 2.0000001E-33 2.0000002E-33 2.0000003E-33 2.0000004E-33
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e-40
Offset: 2.0e-33

Ticks: 2.00000000015E-30 2.0000000002E-30 2.00000000025E-30 2.0000000003E-30
MaxZeroDigits: 3
Labels: 1.5 2.0 2.5 3.0
Exponent: e-40
Offset: 2.0e-30

Ticks: 0.0010000010001 0.0010000010002 0.0010000010003 0.0010000010004
MaxZeroDigits: 3
Labels: 1.0 2.0 3.0 4.0
Exponent: e-13
Offset: 0.001000001

Ticks: 0.0010000010001 0.00100000100015 0.0010000010002 0.00100000100025
MaxZeroDigits: 3
Labels: 1.0 1.5 2.0 2.5
Exponent: e-13
Offset: 0.001000001

Ticks: 1000001000.1 1000001000.2 1000001000.3 1000001000.4
MaxZeroDigits: 3
Labels: 0.1 0.2 0.3 0.4
Exponent:
Offset: 1000001000

Ticks: 1 2 3 4
MaxZeroDigits: 2
Labels: 1 2 3 4
Exponent:
Offset:

Ticks: 10 11 12 13
MaxZeroDigits: 2
Labels: 10 11 12 13
Exponent:
Offset:

Ticks: 100 110 120 130
MaxZeroDigits: 2
Labels: 100 110 120 130
Exponent:
Offset:

Ticks: 1000 1100 1200 1300
MaxZeroDigits: 2
Labels: 1000 1100 1200 1300
Exponent:
Offset:

Ticks: 10000 11000 12000 13000
MaxZeroDigits: 2
Labels: 1.0 1.1 1.2 1.3
Exponent: e+04
Offset:

Ticks: 100000 110000 120000 130000
MaxZeroDigits: 2
Labels: 1.0 1.1 1.2 1.3
Exponent: e+05
Offset:

Ticks: 1.8E+15 1.9E+15 2E+15 2.1E+15
MaxZeroDigits: 2
Labels: 1.8 1.9 2.0 2.1
Exponent: e+15
Offset:

Ticks: 1.8E+35 1.9E+35 2E+35 2.1E+35
MaxZeroDigits: 2
Labels: 1.8 1.9 2.0 2.1
Exponent: e+35
Offset:

Ticks: 2000.000001 2000.0000015 2000.000002 2000.0000025
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset: 2.0e+03

Ticks: 20000.00000105 20000.0000011 20000.00000115 20000.0000012
MaxZeroDigits: 2
Labels: 1.05 1.10 1.15 1.20
Exponent: e-06
Offset: 2.0e+04

Ticks: 2.000001 2.000002 2.000003 2.000004
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 2

Ticks: 20.000001 20.000002 20.000003 20.000004
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 20

Ticks: 200.000001 200.0000015 200.000002 200.0000025
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset: 200

Ticks: 200000.000001 200000.000002 200000.000003 200000.000004
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e-06
Offset: 2.0e+05

Ticks: 2.0000001E+35 2.0000002E+35 2.0000003E+35 2.0000004E+35
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e+29
Offset: 2.0e+35

Ticks: 0.1 0.15 0.2 0.25
MaxZeroDigits: 2
Labels: 0.10 0.15 0.20 0.25
Exponent:
Offset:

Ticks: 0.01 0.015 0.02 0.025
MaxZeroDigits: 2
Labels: 0.010 0.015 0.020 0.025
Exponent:
Offset:

Ticks: 0.001 0.0015 0.002 0.0025
MaxZeroDigits: 2
Labels: 0.0010 0.0015 0.0020 0.0025
Exponent:
Offset:

Ticks: 0.0001 0.00015 0.0002 0.00025
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-04
Offset:

Ticks: 1E-05 1.5E-05 2E-05 2.5E-05
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-05
Offset:

Ticks: 1E-06 1.5E-06 2E-06 2.5E-06
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-06
Offset:

Ticks: 1.8E-13 1.9E-13 2E-13 2.1E-13
MaxZeroDigits: 2
Labels: 1.8 1.9 2.0 2.1
Exponent: e-13
Offset:

Ticks: 1.8E-33 1.9E-33 2E-33 2.1E-33
MaxZeroDigits: 2
Labels: 1.8 1.9 2.0 2.1
Exponent: e-33
Offset:

Ticks: 2.0000001E-33 2.0000002E-33 2.0000003E-33 2.0000004E-33
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e-40
Offset: 2.0e-33

Ticks: 2.00000000015E-30 2.0000000002E-30 2.00000000025E-30 2.0000000003E-30
MaxZeroDigits: 2
Labels: 1.5 2.0 2.5 3.0
Exponent: e-40
Offset: 2.0e-30

Ticks: 0.0010000010001 0.0010000010002 0.0010000010003 0.0010000010004
MaxZeroDigits: 2
Labels: 1.0 2.0 3.0 4.0
Exponent: e-13
Offset: 0.001000001

Ticks: 0.0010000010001 0.00100000100015 0.0010000010002 0.00100000100025
MaxZeroDigits: 2
Labels: 1.0 1.5 2.0 2.5
Exponent: e-13
Offset: 0.001000001

Ticks: 1000001000.1 1000001000.2 1000001000.3 1000001000.4
MaxZeroDigits: 2
Labels: 0.1 0.2 0.3 0.4
Exponent:
Offset: 1.000001e-03


问:
SolrJ CloudSolrClient connection error
I am struggling with indexing using Solrj.

I want to use SolrCloud and I set my connection like this :

SolrClient client = new CloudSolrClient.Builder().withSolrUrl("http://localhost:8983/solr/collectioname").build();
 ```
</div>
</div>
</p>

<p>And I have this error. I checked evruwhere before posting here but I can't resolve it</p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>Exception in thread "main" java.lang.RuntimeException: Couldn't initialize a HttpClusterStateProvider (is/are the Solr server(s), [http://localhost:8983/solr/collectioname], down?)
 at org.apache.solr.client.solrj.impl.CloudSolrClient$Builder.build(CloudSolrClient.java:1496)
 at indexsolr.<init>(indexsolr.java:29)
 at LoadData.toIndex(LoadData.java:100)
 at LoadData.loadDocuments(LoadData.java:72)
 at IndexLaunch.main(IndexLaunch.java:12)
Caused by: org.apache.solr.client.solrj.impl.HttpSolrClient$RemoteSolrException: Error from server at http://localhost:8983/solr/collectioname: Expected mime type application/octet-stream but got text/html. <html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 404 Not Found</title>
</head>
<body><h2>HTTP ERROR 404</h2>
<p>Problem accessing /solr/collectioname/admin/collections. Reason:
```    Not Found```</p>
</body>
</html>

 at org.apache.solr.client.solrj.impl.HttpSolrClient.executeMethod(HttpSolrClient.java:607)
 at org.apache.solr.client.solrj.impl.HttpSolrClient.request(HttpSolrClient.java:255)
 at org.apache.solr.client.solrj.impl.HttpSolrClient.request(HttpSolrClient.java:244)
 at org.apache.solr.client.solrj.SolrClient.request(SolrClient.java:1219)
 at org.apache.solr.client.solrj.impl.HttpClusterStateProvider.fetchLiveNodes(HttpClusterStateProvider.java:189)
 at org.apache.solr.client.solrj.impl.HttpClusterStateProvider.<init>(HttpClusterStateProvider.java:64)
 at org.apache.solr.client.solrj.impl.CloudSolrClient$Builder.build(CloudSolrClient.java:1494)
 ... 4 more</code>```

答:
This is how I did it.
Solr cloud just needs to take a list of urls as a parameter and not just a String url.</p>

```<code>private static final String BASE_SOLR_URL = "http://localhost:8983/solr";
// or initialize a list of solr instances urls

@Bean(name = "solrCloudClient")
public static CloudSolrClient getCloudConnection() {
    System.out.println("----Initializing cloud Solr Connection---");
    List<String> solrCloudUrls = Arrays.asList(BASE_SOLR_URL); // or list of urls

    CloudSolrClient client = new CloudSolrClient.Builder(solrCloudUrls).build();
    client.setParser(new XMLResponseParser());
    return client;
}
</code>```

ContentLicense: CC BY-SA 3.0

Title: SolrJ CloudSolrClient connection error

Body:
I am struggling with indexing using Solrj.

I want to use SolrCloud and I set my connection like this :

SolrClient client = new CloudSolrClient.Builder().withSolrUrl("http://localhost:8983/solr/collectioname").build();

And I have this error. I checked evruwhere before posting here but I can't resolve it

Exception in thread "main" java.lang.RuntimeException: Couldn't initialize a HttpClusterStateProvider (is/are the Solr server(s), [http://localhost:8983/solr/collectioname], down?)
 at org.apache.solr.client.solrj.impl.CloudSolrClient$Builder.build(CloudSolrClient.java:1496)
 at indexsolr.<init>(indexsolr.java:29)
 at LoadData.toIndex(LoadData.java:100)
 at LoadData.loadDocuments(LoadData.java:72)
 at IndexLaunch.main(IndexLaunch.java:12)
Caused by: org.apache.solr.client.solrj.impl.HttpSolrClient$RemoteSolrException: Error from server at http://localhost:8983/solr/collectioname: Expected mime type application/octet-stream but got text/html.

<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 404 Not Found</title>

HTTP ERROR 404

Problem accessing /solr/collectioname/admin/collections. Reason:

    Not Found

 at org.apache.solr.client.solrj.impl.HttpSolrClient.executeMethod(HttpSolrClient.java:607)
 at org.apache.solr.client.solrj.impl.HttpSolrClient.request(HttpSolrClient.java:255)
 at org.apache.solr.client.solrj.impl.HttpSolrClient.request(HttpSolrClient.java:244)
 at org.apache.solr.client.solrj.SolrClient.request(SolrClient.java:1219)
 at org.apache.solr.client.solrj.impl.HttpClusterStateProvider.fetchLiveNodes(HttpClusterStateProvider.java:189)
 at org.apache.solr.client.solrj.impl.HttpClusterStateProvider.<init>(HttpClusterStateProvider.java:64)
 at org.apache.solr.client.solrj.impl.CloudSolrClient$Builder.build(CloudSolrClient.java:1494)
 ... 4 more

Body:
This is how I did it.
Solr cloud just needs to take a list of urls as a parameter and not just a String url.

private static final String BASE_SOLR_URL = "http://localhost:8983/solr";
// or initialize a list of solr instances urls

@Bean(name = "solrCloudClient")
public static CloudSolrClient getCloudConnection() {
    System.out.println("----Initializing cloud Solr Connection---");
    List<String> solrCloudUrls = Arrays.asList(BASE_SOLR_URL); // or list of urls

    CloudSolrClient client = new CloudSolrClient.Builder(solrCloudUrls).build();
    client.setParser(new XMLResponseParser());
    return client;
}


问:
WHAT is the meaning of Leading Length?
I was checking out the difference between char vs varchar2 from google. I came across a word LEADING LENGTH in this link . THERE it was written that

Suppose you store the string ‘ORATABLE’ in a CHAR(20) field and a VARCHAR2(20) field. The CHAR field will use 22 bytes (2 bytes for leading length). The VARCHAR2 field will use 10 bytes only (8 for the string, 2 bytes for leading length).

Q1:How does the char field will use 22 bytes if the string is of 8 characters if (1 byte = 1 char)?

Q2 What is the LEADING LENGTH ? why it does occupy 2 bytes?

答:
The CHAR() datatype pads the string with characters.  So, for 'ORATABLE', it looks like:

```<code>'ORATABLE            '
 12345678901234567890
</code>```

The "leading length" are two bytes at the beginning that specify the length of the string.  Two bytes are needed because one byte is not enough.  Two bytes allow lengths up to 65,535 units; one byte would only allow lengths up to 255.

The important point both CHAR() and VARCHAR2() use the same internal format, so there is little reason to sue CHAR().  Personally, I would only use it for fixed-length codes, such as ISO country codes or US social security numbers.

Title: WHAT is the meaning of Leading Length?

Body:
The CHAR() datatype pads the string with characters.  So, for 'ORATABLE', it looks like:

'ORATABLE            '
 12345678901234567890

The "leading length" are two bytes at the beginning that specify the length of the string.  Two bytes are needed because one byte is not enough.  Two bytes allow lengths up to 65,535 units; one byte would only allow lengths up to 255.

The important point both CHAR() and VARCHAR2() use the same internal format, so there is little reason to sue CHAR().  Personally, I would only use it for fixed-length codes, such as ISO country codes or US social security numbers.


问:
dependency error while adding firebase messaging to a flutter android project
I've added firebase messaging to my Flutter project.

Works fine on iOS, getting an error when trying to run on Android:

```<code>Android dependency 'androidx.localbroadcastmanager:localbroadcastmanager' has different version for the compile (1.0.0-rc01) and runtime (1.0.0) classpath. You should manually set the same version via DependencyResolution
</code>```

My configuration:

in pubspec.yaml

```<code>cloud_firestore: ^0.11.0+2
firebase_auth: ^0.11.1
firebase_messaging: ^5.0.1+1
</code>```

in android/build.gradle

```<code>classpath 'com.google.gms:google-services:4.2.0'
</code>```

in android/app/build.gradle

```<code>implementation 'com.google.firebase:firebase-core:16.0.9'
</code>```

in gradle.properties

```<code>android.useAndroidX=true
android.enableJetifier=true
</code>```

答:
Well, the answer was found here:
https://flutter.dev/docs/development/packages-and-plugins/androidx-compatibility

followed this section: "Manually migrate your app", specifically step 2 helped to sort this out

Body:
I've added firebase messaging to my Flutter project.

Works fine on iOS, getting an error when trying to run on Android:

Android dependency 'androidx.localbroadcastmanager:localbroadcastmanager' has different version for the compile (1.0.0-rc01) and runtime (1.0.0) classpath. You should manually set the same version via DependencyResolution

My configuration:

in pubspec.yaml

cloud_firestore: ^0.11.0+2
firebase_auth: ^0.11.1
firebase_messaging: ^5.0.1+1

in android/build.gradle

classpath 'com.google.gms:google-services:4.2.0'

in android/app/build.gradle

implementation 'com.google.firebase:firebase-core:16.0.9'

in gradle.properties

android.useAndroidX=true
android.enableJetifier=true


问:
How to fix : expected at most 1 argument, got 3
I am trying to ask the user about their favorite subject, but I get the following error message:

Traceback (most recent call last):

File "C:\Users\BillyG\Documents\Revision\ICT\Challenge 5.py", line 2, in
  module

favesub = input("Hello what is your favourite subject", firstname, "?")

TypeError: input expected at most 1 arguments, got 3

The code is:

```<code>firstname=input("What is your name: ")
favesub = input("Hello what is your favorite subject", firstname, "?")
print ("I love ", favesub, "aswell")
</code>```

答:
problem here is that input() method can only take atmost one argument, whereas you are passing 1.</p>

```<code>firstname   = input("What is your name: ")
message     = "Hello what is your favourite subject "+firstname+" ?"
favesub     = input(message)
print ("I love ",favesub," aswell")
</code>```

Body:
I am trying to ask the user about their favorite subject, but I get the following error message:

Traceback (most recent call last):

File "C:\Users\BillyG\Documents\Revision\ICT\Challenge 5.py", line 2, in
  module

favesub = input("Hello what is your favourite subject", firstname, "?")

TypeError: input expected at most 1 arguments, got 3

The code is:

firstname=input("What is your name: ")
favesub = input("Hello what is your favorite subject", firstname, "?")
print ("I love ", favesub, "aswell")

Body:
problem here is that input() method can only take atmost one argument, whereas you are passing 1.

firstname   = input("What is your name: ")
message     = "Hello what is your favourite subject "+firstname+" ?"
favesub     = input(message)
print ("I love ",favesub," aswell")


问:
PHP array_search
Is there any function which will accomplish the equivalent of array_search with a $needle that is an array? Like, this would be an ideal solution:

```<code>$needle = array('first', 'second');
$haystack = array('fifth','second','third', 'first');

// Returns key 1 in haystack
$search = array_search( $needle, $haystack );
</code>```

If no function, any other functions that accept needles which may be arrays that I can use to create a custom function?

答:
You can use array_intersect() : http://php.net/manual/en/function.array-intersect.php</p>

```<code>if (empty(array_intersect($needle, $haystack)) {
   //nothing from needle exists in haystack
}
</code>```

Title: PHP array_search

Body:
Is there any function which will accomplish the equivalent of array_search with a $needle that is an array? Like, this would be an ideal solution:

$needle = array('first', 'second');
$haystack = array('fifth','second','third', 'first');

// Returns key 1 in haystack
$search = array_search( $needle, $haystack );

If no function, any other functions that accept needles which may be arrays that I can use to create a custom function?

Body:
You can use array_intersect() : http://php.net/manual/en/function.array-intersect.php

if (empty(array_intersect($needle, $haystack)) {
   //nothing from needle exists in haystack
}


问:
Correct (technically) handling of cookie consent
I'm about to implement cookie consent for a website. As I understand it, cookie consent means that you shall not use cookies before you have received a consent from the user.

How can I know that a user have accepted cookies or not without storing this information in a cookie?

答:
Check this open source solutionfor the EU cookie law compliance:

https://cookieconsent.osano.com/


问:
How to set mongod.conf bind_ip with multiple ip address
I am a newbie for setting up the server environment and mongoDB. This may sounds something really simple, however, I really need your help on it.

I am trying to connect to my virtual machine which runs the mongodb instance from the local machine, which I believe should be similar to the production environment when I run it on a separate remote server.

The environment is as following:

Private IP for virtual machine: 192.168.184.155

Public IP for both local machine and virtual machine: 96.88.169.145

I changed the bind_ip in /etc/mongod.conf file from

```<code>bind_ip = 127.0.0.1
</code>```

to

```<code>bind_ip = 127.0.0.1,192.168.184.155,96.88.169.145
</code>```

After I restarted the mongod service, neither the virtual machine nor the local machine can access mongodb through mongodb command and giving me the following error.

```<code>MongoDB shell version: 3.0.1
connecting to: test
2015-03-17T16:02:22.705-0400 W NETWORK  Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused
2015-03-17T16:02:22.707-0400 E QUERY    Error: couldn't connect to server 127.0.0.1:27017 (127.0.0.1), connection attempt failed
    at connect (src/mongo/shell/mongo.js:179:14)
    at (connect):1:6 at src/mongo/shell/mongo.js:179
exception: connect failed
</code>```

However, if I change the

```<code>bind_ip = 192.168.184.155
</code>```

and restart the service, it works and I can access using mongo from my local machine. It seems just not work with multiple ip addresses. I tried to do look up in the mongodb document, however, they does mention that bind_ip takes a comma separated list, which really confused me.

Thanks for your help in advance.

答:
The bindIp rule with comma separated IP addresses is only meant for known ethernet interfaces, or for the 0.0.0.0 and 127.0.0.1 rules. You can only use the ip addresses of your system's Network Interface Cards. If this list contains an unknown IP address, i.e. an IP of another system, your MongoDb instance will not restart and hence you're not able to connect. To check if your MongoDb instance is running, run the following:

```<code>$ sudo systemctl status mongod
</code>```

If you would like to make your MongoDb instance available to other systems on your network, you'll want to bind the local IP associated with the private network. To determine network interface configuration easily, just run an ifconfig from the command line:

```<code>$ ifconfig
</code>```

This will list all available IP addresses that you can use in the bindIp rule. Most certainly, the IP address 96.88.169.145 that you use is not a valid IP address or unknown by your system.

Body:
I am a newbie for setting up the server environment and mongoDB. This may sounds something really simple, however, I really need your help on it.

I am trying to connect to my virtual machine which runs the mongodb instance from the local machine, which I believe should be similar to the production environment when I run it on a separate remote server.

The environment is as following:

Private IP for virtual machine: 192.168.184.155

Public IP for both local machine and virtual machine: 96.88.169.145

I changed the bind_ip in /etc/mongod.conf file from

bind_ip = 127.0.0.1

to

bind_ip = 127.0.0.1,192.168.184.155,96.88.169.145

After I restarted the mongod service, neither the virtual machine nor the local machine can access mongodb through mongodb command and giving me the following error.

MongoDB shell version: 3.0.1
connecting to: test
2015-03-17T16:02:22.705-0400 W NETWORK  Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused
2015-03-17T16:02:22.707-0400 E QUERY    Error: couldn't connect to server 127.0.0.1:27017 (127.0.0.1), connection attempt failed
    at connect (src/mongo/shell/mongo.js:179:14)
    at (connect):1:6 at src/mongo/shell/mongo.js:179
exception: connect failed

However, if I change the

bind_ip = 192.168.184.155

and restart the service, it works and I can access using mongo from my local machine. It seems just not work with multiple ip addresses. I tried to do look up in the mongodb document, however, they does mention that bind_ip takes a comma separated list, which really confused me.

Thanks for your help in advance.

Body:
The bindIp rule with comma separated IP addresses is only meant for known ethernet interfaces, or for the 0.0.0.0 and 127.0.0.1 rules. You can only use the ip addresses of your system's Network Interface Cards. If this list contains an unknown IP address, i.e. an IP of another system, your MongoDb instance will not restart and hence you're not able to connect. To check if your MongoDb instance is running, run the following:

$ sudo systemctl status mongod

If you would like to make your MongoDb instance available to other systems on your network, you'll want to bind the local IP associated with the private network. To determine network interface configuration easily, just run an ifconfig from the command line:

$ ifconfig

This will list all available IP addresses that you can use in the bindIp rule. Most certainly, the IP address 96.88.169.145 that you use is not a valid IP address or unknown by your system.


问:
iOS Swift - Passing data from First ViewController to Third ViewConTroller
For example, my app has 3 ViewControllers: A, B, C
I use Segue to move A->B->C. My problem is that at ViewController C, I want to get directly data of ViewController A, without passing data from A->B, then B->C.
Is it possible?

For more detail: I made a form with many steps (Step A->B->C then submitting). So at the final step, I want to collect all user's input at each step and submit them.

How can I get all data at the final step?

1. Store data temporarily somewhere then getting at final step

2. At final step, directly getting data of each step by some magic?

答:
If you are using a NavigationController you can access each controller pushed to it directly through it by addressing it's viewControllers[index].

For example you can use a custom NavigationController by overriding the default class and store each step's data in it which is accessible by all of view controllers pushed inside it and in C you can retrieve them like this:

```<code>let navVC = self.navigationController as? YourCustomNavigationController
let data = navVC.getData()
</code>```

or just save data temporarily in AppDelegate and it will be accessible anywhere in your app which is not recommended because it makes your code dirty

If it was not helpful please give me more information about your app structure and what are you trying to do :)

Create a new cocoa touch class and name it like : CustomNavigationController and make it subclass of UINavigationController and if you are using a storyboard set the navigation controller class which A is pushed into it to CustomNavigationController (under identity inspector tab) in Interface builder

Then you can add your properties and methods to CustomNavigationController like :

```<code>var data : AnyObject?

func storeData(data:AnyObject){

}

func getData() -> AnyObject? {
    return data
}
</code>```

And from any view controller of it pass the value to Navigation Controller :

```<code>let navVC = self.navigationController as! CustomNavigationController
        navVC.storeData(data: myData)
    }
</code>```

Body:
If you are using a NavigationController you can access each controller pushed to it directly through it by addressing it's viewControllers[index].

For example you can use a custom NavigationController by overriding the default class and store each step's data in it which is accessible by all of view controllers pushed inside it and in C you can retrieve them like this:

let navVC = self.navigationController as? YourCustomNavigationController
let data = navVC.getData()

or just save data temporarily in AppDelegate and it will be accessible anywhere in your app which is not recommended because it makes your code dirty

If it was not helpful please give me more information about your app structure and what are you trying to do :)

Create a new cocoa touch class and name it like : CustomNavigationController and make it subclass of UINavigationController and if you are using a storyboard set the navigation controller class which A is pushed into it to CustomNavigationController (under identity inspector tab) in Interface builder

Then you can add your properties and methods to CustomNavigationController like :

var data : AnyObject?

func storeData(data:AnyObject){

}

func getData() -> AnyObject? {
    return data
}

And from any view controller of it pass the value to Navigation Controller :

let navVC = self.navigationController as! CustomNavigationController
        navVC.storeData(data: myData)
    }


问:
For a shared resource accessed by two threads, how to arrange priority?
Is there a way to give one thread priority over another when accessing the resource?</p>

答:
If I understand your question correctly, you are seeking a solution where if a Thread (H) with high priority wants to access a resource, then if another thread (L) with lower priority is accessing it, you want to stop it or make it release the resource.

If that is the case, then you will have to either send a message to L via a method call or the thread L will have to keep checking some flag value that can be set by thread H, when it wants to access the resource. Thread L can then release the resource and wait for some time before trying to use the resource again.


问:
Eclipse dark theme highlight issue
I just switched from geany to eclipse and I have a little problem

How can I change that highlight color which is VERY annoying

As you can see, whenever I highlight anything and click somewhere else, it changes like this. How can fix this little bug?

答:
Annotations is the setting you want to Change (whatever Eclipse you are using - example below is CDT):
annotations / Occurences in Eclipse preferences</p>

Title: Eclipse dark theme highlight issue


问:
Search for string to move one row lower
Sheet contains commission data for employees.

Data is dumped out of Accounting system each week.

Need to move a cell value "Totals" down 1 row to align with the relevant data.

Have tried to search for the string "Totals" then cut and paste 1 row lower.

The string is in col-A.  The dataset size and content rows is variable each week but the target string is always in col-A and needs to drop down 1 row, probably with an offset (1, 0) style of command?

Dim m As Integer
m = 2

Do Until m = 300 'this is set to cover the expected occurrences

    On Error Resume Next
    Range(A1, A300).Cells("m", 0).Find(What:="Totals").Offset(1, 0) = "TOTALS"
    m = m + 1
    On Error GoTo 0

Loop
```

Getting no error messages but no results either!

答:
So this is what I think you are after. Define the range where the "Totals" lie - assuming they are in a Row? See below code.

```<code>Sub LoopTotals()

    Dim cell As Range
    Dim myRange As Range

    'set the range
    Set myRange = Sheet1.Range("A1:AA1")

    'loop through range
    For Each cell In myRange
        'check if text is "Totals"
        If Trim(cell.Text) = "Totals" Then
            'set the new "Totals" 1 row lower
            cell.Offset(1, 0).Value = "Totals"
            'delete the old string value
            cell.ClearContents
        End If
    Next

End Sub
</code>```

Additionally, if the "Totals" are pulled in differently each time from the accounting software then you can run a search to find the "Totals" and then you can reference that row number for you range.

Title: Search for string to move one row lower

Body:
Sheet contains commission data for employees.

Data is dumped out of Accounting system each week.

Need to move a cell value "Totals" down 1 row to align with the relevant data.

Have tried to search for the string "Totals" then cut and paste 1 row lower.

The string is in col-A.  The dataset size and content rows is variable each week but the target string is always in col-A and needs to drop down 1 row, probably with an offset (1, 0) style of command?

Dim m As Integer
m = 2

Do Until m = 300 'this is set to cover the expected occurrences

    On Error Resume Next
    Range(A1, A300).Cells("m", 0).Find(What:="Totals").Offset(1, 0) = "TOTALS"
    m = m + 1
    On Error GoTo 0

Loop

Getting no error messages but no results either!

Body:
So this is what I think you are after. Define the range where the "Totals" lie - assuming they are in a Row? See below code.

Sub LoopTotals()

    Dim cell As Range
    Dim myRange As Range

    'set the range
    Set myRange = Sheet1.Range("A1:AA1")

    'loop through range
    For Each cell In myRange
        'check if text is "Totals"
        If Trim(cell.Text) = "Totals" Then
            'set the new "Totals" 1 row lower
            cell.Offset(1, 0).Value = "Totals"
            'delete the old string value
            cell.ClearContents
        End If
    Next

End Sub

Additionally, if the "Totals" are pulled in differently each time from the accounting software then you can run a search to find the "Totals" and then you can reference that row number for you range.