问:
Excel VBA sum with dynamic range
I'm trying to create a excel macro calculating a sum of values in column A, using a certain dynamic range.

Basic excel example screenshot included below:

The final goal is to loop through the cells in column B till a "0" is reached. When a "0" is reached, in column A of that same row, a sum of all the values in column A is calculated until a new "0" in column B is reached.
So in this basic example A1 should contain =sum(A2:A7) and A8 should contain the sum of the values A9 through A14.

My progress so far included below, still pretty new at all the VBA stuff.

```<code>Sub sumtill0()
'
' sumtill0 Macro
'

'
Cells(ActiveCell.Row, 1).Select
If Sheets("Blad1").Cells(2, 1).Value = nil And Sheets("Blad1").Cells(2, 1).Value <> "0" Then
    Sheets("Blad1").Activate
    Cells(2, 1).Range("A1").Select
       Else
    Dim artTekst As String
    If Sheets("Blad1").Cells(1, 2).Value = "0" Then
        Sheets("Blad1").Cells(1, 1).Fomula = "=SUM()"
    Else
        If Sheets("Blad1").Cells(1, 2).End(xlDown).Value = "0" Then
            Sheets("Blad1").Cells(1, 1).End(xlDown).Offset(1, 0).Value = "0"
            Sheets("Blad1").Cells(1, 1).End(xlDown).Fomula = "=SUM(???)"
            ActiveCell.Value = Sheets("Blad1").Cells(1, 2).End(xlDown).Offset(0, -2).Value
    End If

End If

End If

End Sub
</code>```

Thanks :)

答:
Think this does what you want. It uses the Find method to find successive zeros and sums the range between each pair. If it cycles back to the start value, it sums to the bottom value (not sure what should happen if the first value in B is not zero).</p>

```<code>Sub x()

Dim rFind As Range, s As String, r1 As Range

With Range("B1", Range("B" & Rows.Count).End(xlUp))
    Set rFind = .Find(What:=0, After:=.Cells(.Cells.Count), LookIn:=xlFormulas, _
                      Lookat:=xlWhole, SearchDirection:=xlNext, searchFormat:=False)
    If Not rFind Is Nothing Then
        s = rFind.Address
        Do
            Set r1 = rFind
            Set rFind = .FindNext(rFind)
            If rFind.Address = s Then
                Set rFind = .Cells(.Cells.Count)
                r1.Offset(, -1).Value = Application.Sum(Range(r1.Offset(1, -1), rFind.Offset(, -1)))
                Exit Sub
            End If
            r1.Offset(, -1).Value = Application.Sum(Range(r1.Offset(1, -1), rFind.Offset(-1, -1)))
        Loop While rFind.Address <> s
    End If
End With

End Sub
</code>```

Title: Excel VBA sum with dynamic range

Body:
I'm trying to create a excel macro calculating a sum of values in column A, using a certain dynamic range.

Basic excel example screenshot included below:

The final goal is to loop through the cells in column B till a "0" is reached. When a "0" is reached, in column A of that same row, a sum of all the values in column A is calculated until a new "0" in column B is reached.
So in this basic example A1 should contain =sum(A2:A7) and A8 should contain the sum of the values A9 through A14.

My progress so far included below, still pretty new at all the VBA stuff.

Sub sumtill0()
'
' sumtill0 Macro
'

'
Cells(ActiveCell.Row, 1).Select
If Sheets("Blad1").Cells(2, 1).Value = nil And Sheets("Blad1").Cells(2, 1).Value <> "0" Then
    Sheets("Blad1").Activate
    Cells(2, 1).Range("A1").Select
       Else
    Dim artTekst As String
    If Sheets("Blad1").Cells(1, 2).Value = "0" Then
        Sheets("Blad1").Cells(1, 1).Fomula = "=SUM()"
    Else
        If Sheets("Blad1").Cells(1, 2).End(xlDown).Value = "0" Then
            Sheets("Blad1").Cells(1, 1).End(xlDown).Offset(1, 0).Value = "0"
            Sheets("Blad1").Cells(1, 1).End(xlDown).Fomula = "=SUM(???)"
            ActiveCell.Value = Sheets("Blad1").Cells(1, 2).End(xlDown).Offset(0, -2).Value
    End If

End If

End If

End Sub

Thanks :)

Body:
Think this does what you want. It uses the Find method to find successive zeros and sums the range between each pair. If it cycles back to the start value, it sums to the bottom value (not sure what should happen if the first value in B is not zero).

Sub x()

Dim rFind As Range, s As String, r1 As Range

With Range("B1", Range("B" & Rows.Count).End(xlUp))
    Set rFind = .Find(What:=0, After:=.Cells(.Cells.Count), LookIn:=xlFormulas, _
                      Lookat:=xlWhole, SearchDirection:=xlNext, searchFormat:=False)
    If Not rFind Is Nothing Then
        s = rFind.Address
        Do
            Set r1 = rFind
            Set rFind = .FindNext(rFind)
            If rFind.Address = s Then
                Set rFind = .Cells(.Cells.Count)
                r1.Offset(, -1).Value = Application.Sum(Range(r1.Offset(1, -1), rFind.Offset(, -1)))
                Exit Sub
            End If
            r1.Offset(, -1).Value = Application.Sum(Range(r1.Offset(1, -1), rFind.Offset(-1, -1)))
        Loop While rFind.Address <> s
    End If
End With

End Sub


来源: stackexchange

问:
In Windows batch loop, how to wait for spawned processes to complete before continuing
I want to fire off multiple commands within a loop in a batch file like this:

```<code>for /l %%x in (20170101,1,20170105) do (
start /wait C:\Progra~1\Amazon\AWSCLI\aws s3 cp s3://bucket1/%%x
s3://bucket2/%%x --recursive
)

#do something else here only when ALL the above commands complete
</code>```

Will the Start /wait have the effect of waiting until all commands complete before moving to next line after the loop?

答:
start /wait isn't "global", it just waits for the started process to finish (maybe... depends on how the application is programmed). What you need (starting several processes in parallel and wait until the last is finished) can be done with a different method: give all your processes a defined title and watch them:

```<code>@echo off
setlocal enabledelayedexpansion
for /l %%i in (1,1,10) do (
   start "OneOfMyProcesses" timeout !random:~-1!
)
echo waiting
:loop
timeout 1 >nul
tasklist /v |find "OneOfMyProcesses" >nul && goto :loop
echo all of them are finished
</code>```

Note: as mentioned above, this may or may not work with your application

ContentLicense: CC BY-SA 3.0

Body:
I want to fire off multiple commands within a loop in a batch file like this:

for /l %%x in (20170101,1,20170105) do (
start /wait C:\Progra~1\Amazon\AWSCLI\aws s3 cp s3://bucket1/%%x
s3://bucket2/%%x --recursive
)

#do something else here only when ALL the above commands complete

Will the Start /wait have the effect of waiting until all commands complete before moving to next line after the loop?

Body:
start /wait isn't "global", it just waits for the started process to finish (maybe... depends on how the application is programmed). What you need (starting several processes in parallel and wait until the last is finished) can be done with a different method: give all your processes a defined title and watch them:

@echo off
setlocal enabledelayedexpansion
for /l %%i in (1,1,10) do (
   start "OneOfMyProcesses" timeout !random:~-1!
)
echo waiting
:loop
timeout 1 >nul
tasklist /v |find "OneOfMyProcesses" >nul && goto :loop
echo all of them are finished

Note: as mentioned above, this may or may not work with your application


问:
Trying to understand class and instance
I'm half way through 'real world haskell' and thought I'd have a go at writing my first code. Didn't get very far...

Basically, I thought I'd try and implement an array syntax for doubles and double lists so I can do numerical calculations on lists. Am I right in thinking that 'class' is like a generic function in CLOS? I made a 'class' with a function arplus to add arrays and scalars, and made it work for scalars. Now I don't know how to do the same for lists. (Doing the calculation is easy, I just don't know what to put in place of 'Double' for the list version).

```<code>class Narray a where
    arplus :: a -> a -> a

instance Narray Double where
    arplus a b =  a + b
</code>```

Then, how do I do mixed versions? Array-scalar and scalar array?

Will I need something like:

```<code>class Narray a where
   arplus :: a -> b -> a
</code>```

instead?

As an example of the code I'm trying to write, see the sbcl code below:
(Note - I've done this with arrays in lisp, but I was doing it in lists in haskell as they're typed. Doesn't really matter in terms of the question 'though.)

```<code>;; Generic add for arrays and scalar
(defgeneric .+ (a b))

;; Scalar-scalar
(defmethod .+ ((a double-float) (b double-float)) (+ a b))

;; Array-array
(defmethod .+ ((a SB-KERNEL::SIMPLE-ARRAY-DOUBLE-FLOAT)
       (b SB-KERNEL::SIMPLE-ARRAY-DOUBLE-FLOAT))
     (dotimes (i (array-total-size a))
        (setf (row-major-aref a i)
        (+ (row-major-aref a i)
           (row-major-aref b i)))) a)

;; Array-scaler
(defmethod .+ ((a SB-KERNEL::SIMPLE-ARRAY-DOUBLE-FLOAT) (b double-float))
  (dotimes (i (array-total-size a))
      (setf (row-major-aref a i)
        (+ (row-major-aref a i)
           b))) a)

;; Scalar-array
(defmethod .+ ((a double-float) (b SB-KERNEL::SIMPLE-ARRAY-DOUBLE-FLOAT))
  (dotimes (i (array-total-size b))
      (setf (row-major-aref b i)
        (+ a
           (row-major-aref b i)))) b)

;; Just to demo the code
(defun indgen (n)
  (let ((r (make-array n :element-type 'double-float)))
    (dotimes (i n)
      (setf (row-major-aref r i) (coerce i 'double-float))) r))

* (load "arrays.lisp")

T
* (.+ (indgen 6) 10d0)

#(10.0d0 11.0d0 12.0d0 13.0d0 14.0d0 15.0d0)
* (.+ (indgen 6) (indgen 6))

#(0.0d0 2.0d0 4.0d0 6.0d0 8.0d0 10.0d0)
*
</code>```

答:
Can't answer the whole question, but for the list version, I got this to work:

```<code>main = [1, 2, 3] `arplus` [4, 5, 6]

class Narry a where
    arplus :: a → a → a

instance (Num a) ⇒ Narry [a] where
    arplus = zipWith (+)
</code>```

I also tried turning (Num a) => [a] into an instance of Num, which had some nice results.

```<code>instance (Num a) ⇒ Num [a] where
    (+) = zipWith (+)
    (*) = zipWith (*)
    (-) = zipWith (-)
    negate = map negate
    abs    = map abs
    signum = map signum
    fromInteger = repeat∘fromInteger
</code>```

You can try it out just like this

```<code>main = do print $ [1, 2, 3] * 3   -- [3, 6, 9]
          print $ 3 * [1, 2, 3]   -- [3, 6, 9]
          print $ 3 - [2, 4, 6]   -- [-1, 1, 3]
          print $ [2, 4, 6] + 7   -- [9, 11, 13]
          print $ abs [-2, 4, -3] -- [2, 4, 3]
          print $ [1, 2, 3] + [4.3, 5.5, 6.7] -- [5.3, 7.5, 9.7]
          print $ [1, 2, 3] * [3, 4, 5] -- [3, 8, 15]
</code>```

Of course, if you want to do Double arithmetic with lists, then you'll have to write definitions for some more stuff. I am not sure what the extent of my definition here can do, though I suspect it's not much more than what I've demonstrated.

Also, this isn't the only way to make lists of Nums an instance of Num; there are probably better choices than zipWith for (*).

[EDIT] Making lists an instance of Fractional is trivially easy and adds some more handy functinality.

```<code>instance (Fractional a) => Fractional [a] where
    recip = map recip
    fromRational = repeat . fromRational
</code>```

This makes list-with-fractional interactions possible, and divide works auto-magically!

```<code>ghci> [3, 6, 9] / 3
[1.0,2.0,3.0]
ghci> 9 / [1, 2, 3]
[9.0,4.5,3.0]
ghci> 1.2 + [0, 1, 2]
[1.2,2.2,3.2]
</code>```

With great power comes great responsibility; only use these if you need them. If you don't need this behavior, then it's nice to have the compiler yell at you when you try to invoke + on a number and a list.

Title: Trying to understand class and instance

Body:
I'm half way through 'real world haskell' and thought I'd have a go at writing my first code. Didn't get very far...

Basically, I thought I'd try and implement an array syntax for doubles and double lists so I can do numerical calculations on lists. Am I right in thinking that 'class' is like a generic function in CLOS? I made a 'class' with a function arplus to add arrays and scalars, and made it work for scalars. Now I don't know how to do the same for lists. (Doing the calculation is easy, I just don't know what to put in place of 'Double' for the list version).

class Narray a where
    arplus :: a -> a -> a

instance Narray Double where
    arplus a b =  a + b

Then, how do I do mixed versions? Array-scalar and scalar array?

Will I need something like:

class Narray a where
   arplus :: a -> b -> a

instead?

As an example of the code I'm trying to write, see the sbcl code below:
(Note - I've done this with arrays in lisp, but I was doing it in lists in haskell as they're typed. Doesn't really matter in terms of the question 'though.)

;; Generic add for arrays and scalar
(defgeneric .+ (a b))

;; Scalar-scalar
(defmethod .+ ((a double-float) (b double-float)) (+ a b))

;; Array-array
(defmethod .+ ((a SB-KERNEL::SIMPLE-ARRAY-DOUBLE-FLOAT)
       (b SB-KERNEL::SIMPLE-ARRAY-DOUBLE-FLOAT))
     (dotimes (i (array-total-size a))
        (setf (row-major-aref a i)
        (+ (row-major-aref a i)
           (row-major-aref b i)))) a)

;; Array-scaler
(defmethod .+ ((a SB-KERNEL::SIMPLE-ARRAY-DOUBLE-FLOAT) (b double-float))
  (dotimes (i (array-total-size a))
      (setf (row-major-aref a i)
        (+ (row-major-aref a i)
           b))) a)

;; Scalar-array
(defmethod .+ ((a double-float) (b SB-KERNEL::SIMPLE-ARRAY-DOUBLE-FLOAT))
  (dotimes (i (array-total-size b))
      (setf (row-major-aref b i)
        (+ a
           (row-major-aref b i)))) b)

;; Just to demo the code
(defun indgen (n)
  (let ((r (make-array n :element-type 'double-float)))
    (dotimes (i n)
      (setf (row-major-aref r i) (coerce i 'double-float))) r))

* (load "arrays.lisp")

T
* (.+ (indgen 6) 10d0)

#(10.0d0 11.0d0 12.0d0 13.0d0 14.0d0 15.0d0)
* (.+ (indgen 6) (indgen 6))

#(0.0d0 2.0d0 4.0d0 6.0d0 8.0d0 10.0d0)
*

Body:
Can't answer the whole question, but for the list version, I got this to work:

main = [1, 2, 3] `arplus` [4, 5, 6]

class Narry a where
    arplus :: a → a → a

instance (Num a) ⇒ Narry [a] where
    arplus = zipWith (+)

I also tried turning (Num a) => [a] into an instance of Num, which had some nice results.

instance (Num a) ⇒ Num [a] where
    (+) = zipWith (+)
    (*) = zipWith (*)
    (-) = zipWith (-)
    negate = map negate
    abs    = map abs
    signum = map signum
    fromInteger = repeat∘fromInteger

You can try it out just like this

main = do print $ [1, 2, 3] * 3   -- [3, 6, 9]
          print $ 3 * [1, 2, 3]   -- [3, 6, 9]
          print $ 3 - [2, 4, 6]   -- [-1, 1, 3]
          print $ [2, 4, 6] + 7   -- [9, 11, 13]
          print $ abs [-2, 4, -3] -- [2, 4, 3]
          print $ [1, 2, 3] + [4.3, 5.5, 6.7] -- [5.3, 7.5, 9.7]
          print $ [1, 2, 3] * [3, 4, 5] -- [3, 8, 15]

Of course, if you want to do Double arithmetic with lists, then you'll have to write definitions for some more stuff. I am not sure what the extent of my definition here can do, though I suspect it's not much more than what I've demonstrated.

Also, this isn't the only way to make lists of Nums an instance of Num; there are probably better choices than zipWith for (*).

[EDIT] Making lists an instance of Fractional is trivially easy and adds some more handy functinality.

instance (Fractional a) => Fractional [a] where
    recip = map recip
    fromRational = repeat . fromRational

This makes list-with-fractional interactions possible, and divide works auto-magically!

ghci> [3, 6, 9] / 3
[1.0,2.0,3.0]
ghci> 9 / [1, 2, 3]
[9.0,4.5,3.0]
ghci> 1.2 + [0, 1, 2]
[1.2,2.2,3.2]

With great power comes great responsibility; only use these if you need them. If you don't need this behavior, then it's nice to have the compiler yell at you when you try to invoke + on a number and a list.

ContentLicense: CC BY-SA 2.5


问:
Xcode - Simulator shows views different from Storyboard
Auto Layout on Storyboard is working fine, different screens are correctly lay out when I change the view (iPad, iPhone).

However, when using Simulator, the result is different than on Storyboard (note the green arrows).

答:
The button with the text 1X in the lower-right corner indicates that your app is not scaled properly and is iPhone only.

Under Project settings/Targets/[your target]/General/Deployment Info/Devices, check Universal instead of iPhone.


问:
How to dynamically route message to queues in RabbitMQ
I want to develop solutions that can dynamically route messages to different queues (more than 10000 queues). That's what I have so far:

Exchange with type set to topic. So that I can route messages to different queues based on routing keys.

10000 queues that have routing key as #.%numberOfQueue.#. The %numberOfQueue% is simple numeric value for that queue (but it might be changed for more meaningfull ones).

Producer producing message with routing key like that: 5.10.15.105.10000 which means that message should be routed to queue with keys 5, 10, 15, 105 and 10000 as they comform the patterns of that queues.

That's how it looks like from java client API:

```<code>String exchangeName = "rabbit.test.exchange";
String exchangeType = "topic";
boolean exchangeDurable = true;
boolean queueDurable = true;
boolean queueExclusive = false;
boolean queueAutoDelete = false;
Map<String, Object> queueArguments = null;

for (int i = 0; i < numberOfQueues; i++) {
    String queueNameIterated = "rabbit.test" + i + ".queue";
    channel.exchangeDeclare(exchangeName, exchangeType, exchangeDurable);
    channel.queueDeclare(queueNameIterated, queueDurable, queueExclusive, queueAutoDelete, queueArguments);

    String routingKey = "#." + i + ".#";
    channel.queueBind(queueNameIterated, exchangeName, routingKey);
}
</code>```

That's how routingKey generated for all messages for queues from 0 to 9998:

```<code>private String generateRoutingKey() {
    StringBuilder keyBuilder = new StringBuilder();
    for (int i = 0; i < numberOfQueues - 2; i++) {
        keyBuilder.append(i);
        keyBuilder.append('.');
    }
    String result = keyBuilder.append(numberOfQueues - 2).toString();
    LOGGER.info("generated key: {}", result);
    return result;
}
</code>```

Seems good. The problem is that I can't use such long routingKey with channel.basicPublish() method:

Exception in thread "main" java.lang.IllegalArgumentException: Short string too long; utf-8 encoded length = 48884, max = 255.
      at com.rabbitmq.client.impl.ValueWriter.writeShortstr(ValueWriter.java:50)
      at com.rabbitmq.client.impl.MethodArgumentWriter.writeShortstr(MethodArgumentWriter.java:74)
      at com.rabbitmq.client.impl.AMQImpl$Basic$Publish.writeArgumentsTo(AMQImpl.java:2319)
      at com.rabbitmq.client.impl.Method.toFrame(Method.java:85)
      at com.rabbitmq.client.impl.AMQCommand.transmit(AMQCommand.java:104)
      at com.rabbitmq.client.impl.AMQChannel.quiescingTransmit(AMQChannel.java:396)
      at com.rabbitmq.client.impl.AMQChannel.transmit(AMQChannel.java:372)
      at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:690)
      at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:672)
      at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:662)
      at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.basicPublish(AutorecoveringChannel.java:192)

I have requirements:

Dynamically choose from producer in which queues produce the messages. It might be just one queue, all queues or 1000 queues.

I have more than 10000 different queues and it might be needed to produce same message to them.

So the questions are:

Can I use such long key? If can - how to do it?

Maybe I can achieve the same goal by different configuration of exchange or queues?

Maybe there are some hash function that can effectivily distinguesh destinations and collapse that in 255 symbols? If so, It should provide way to deal with different publishings (for example how to send to only queues numbered 555 and 8989?)?

Maybe there are some different key strategy that could be used in that way?

How else I can achieve my requirements?

答:
I started using RabbitQM just a short time ago, hope I can help you nonetheless. There can be as many words in the routing key as you like, up to the limit of 255 bytes (as also described in e.g. RabbitMQ Tutorial 5 - Topics). Thus, the topics exchange does not seem to be appropriate for your use case.

Perhaps you can use a headers exchange in this case? According to the concept description:

A headers exchange is designed for routing on multiple attributes that are more easily expressed as message headers than a routing key. Headers exchanges ignore the routing key attribute. Instead, the attributes used for routing are taken from the headers attribute. A message is considered matching if the value of the header equals the value specified upon binding.

See here and here for an example. As I said, I just started with RabbitMQ, therefore, I don't know for sure whether this could be an option for you. If I have time later I try to construct a simple example for you.

ContentLicense: CC BY-SA 4.0

Body:
I want to develop solutions that can dynamically route messages to different queues (more than 10000 queues). That's what I have so far:

Exchange with type set to topic. So that I can route messages to different queues based on routing keys.

10000 queues that have routing key as #.%numberOfQueue.#. The %numberOfQueue% is simple numeric value for that queue (but it might be changed for more meaningfull ones).

Producer producing message with routing key like that: 5.10.15.105.10000 which means that message should be routed to queue with keys 5, 10, 15, 105 and 10000 as they comform the patterns of that queues.

That's how it looks like from java client API:

String exchangeName = "rabbit.test.exchange";
String exchangeType = "topic";
boolean exchangeDurable = true;
boolean queueDurable = true;
boolean queueExclusive = false;
boolean queueAutoDelete = false;
Map<String, Object> queueArguments = null;

for (int i = 0; i < numberOfQueues; i++) {
    String queueNameIterated = "rabbit.test" + i + ".queue";
    channel.exchangeDeclare(exchangeName, exchangeType, exchangeDurable);
    channel.queueDeclare(queueNameIterated, queueDurable, queueExclusive, queueAutoDelete, queueArguments);

    String routingKey = "#." + i + ".#";
    channel.queueBind(queueNameIterated, exchangeName, routingKey);
}

That's how routingKey generated for all messages for queues from 0 to 9998:

private String generateRoutingKey() {
    StringBuilder keyBuilder = new StringBuilder();
    for (int i = 0; i < numberOfQueues - 2; i++) {
        keyBuilder.append(i);
        keyBuilder.append('.');
    }
    String result = keyBuilder.append(numberOfQueues - 2).toString();
    LOGGER.info("generated key: {}", result);
    return result;
}

Seems good. The problem is that I can't use such long routingKey with channel.basicPublish() method:

Exception in thread "main" java.lang.IllegalArgumentException: Short string too long; utf-8 encoded length = 48884, max = 255.
      at com.rabbitmq.client.impl.ValueWriter.writeShortstr(ValueWriter.java:50)
      at com.rabbitmq.client.impl.MethodArgumentWriter.writeShortstr(MethodArgumentWriter.java:74)
      at com.rabbitmq.client.impl.AMQImpl$Basic$Publish.writeArgumentsTo(AMQImpl.java:2319)
      at com.rabbitmq.client.impl.Method.toFrame(Method.java:85)
      at com.rabbitmq.client.impl.AMQCommand.transmit(AMQCommand.java:104)
      at com.rabbitmq.client.impl.AMQChannel.quiescingTransmit(AMQChannel.java:396)
      at com.rabbitmq.client.impl.AMQChannel.transmit(AMQChannel.java:372)
      at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:690)
      at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:672)
      at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:662)
      at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.basicPublish(AutorecoveringChannel.java:192)

I have requirements:

Dynamically choose from producer in which queues produce the messages. It might be just one queue, all queues or 1000 queues.

I have more than 10000 different queues and it might be needed to produce same message to them.

So the questions are:

Can I use such long key? If can - how to do it?

Maybe I can achieve the same goal by different configuration of exchange or queues?

Maybe there are some hash function that can effectivily distinguesh destinations and collapse that in 255 symbols? If so, It should provide way to deal with different publishings (for example how to send to only queues numbered 555 and 8989?)?

Maybe there are some different key strategy that could be used in that way?

How else I can achieve my requirements?


问:
How to add progress bar until loop execution is finished?
I am developing an android app where I need to show a ProgressBar until the loop execution is finished. After execution it will go to the nextActivity.

here is my java code

```<code>    public class Image_Recognition extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image__recognition);

        Button btnNextPage = (Button) findViewById(R.id.btnNextPage);

            btnNextPage.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    TextRecognizer textRecognizer = new TextRecognizer.Builder(getApplicationContext()).build();

                        Frame frame = new Frame.Builder().setBitmap(bitmap).build();
                        SparseArray<TextBlock> items = textRecognizer.detect(frame);
                        StringBuilder stringBuilder = new StringBuilder();
                        for (int i = 0; i < items.size(); ++i) {
                            TextBlock item = items.valueAt(i);
                            stringBuilder.append(item.getValue());
                            stringBuilder.append("\n");
                        }
                        stringBuilder.append('.');
                        txtResult.setText(stringBuilder.toString());

                        str = stringBuilder.toString();
                        Intent myintent = new Intent(Image_Recognition.this, ReminderAddActivity.class);
                        myintent.putExtra("translate", str);
                        startActivity(myintent);

                }
            });
        }
    //}
}
</code>```

答:
You have two problems here.

ProgressBar, which you can use ProgressDialog or a ProgressBar in your XML and show it, while hiding the rest of your IU.

Blocking the UI

You are running your loop directly from you click listener, which means that you will block your UI and even if you show some sort of progress, it will be blocked till your loop is over, you need to start a thread and run your loop in.

Here's a not very clean version of you click listener impl

```<code>final ProgressDialog dialog = new ProgressDialog(Image_Recognition.this);
        dialog.show();

        new Thread(new Runnable() {
            @Override
            public void run() {
                TextRecognizer textRecognizer = new TextRecognizer.Builder(getApplicationContext()).build();

                Frame frame = new Frame.Builder().setBitmap(bitmap).build();
                SparseArray<TextBlock> items = textRecognizer.detect(frame);
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < items.size(); ++i) {
                    TextBlock item = items.valueAt(i);
                    stringBuilder.append(item.getValue());
                    stringBuilder.append("\n");
                }
                stringBuilder.append('.');
                txtResult.setText(stringBuilder.toString());

                str = stringBuilder.toString();

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        dialog.dismiss();
                        Intent myintent = new Intent(Image_Recognition.this, ReminderAddActivity.class);
                        myintent.putExtra("translate", str);
                        startActivity(myintent);
                    }
                });
            }
        }).start();
</code>```

Body:
I am developing an android app where I need to show a ProgressBar until the loop execution is finished. After execution it will go to the nextActivity.

here is my java code

    public class Image_Recognition extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image__recognition);

        Button btnNextPage = (Button) findViewById(R.id.btnNextPage);

            btnNextPage.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    TextRecognizer textRecognizer = new TextRecognizer.Builder(getApplicationContext()).build();

                        Frame frame = new Frame.Builder().setBitmap(bitmap).build();
                        SparseArray<TextBlock> items = textRecognizer.detect(frame);
                        StringBuilder stringBuilder = new StringBuilder();
                        for (int i = 0; i < items.size(); ++i) {
                            TextBlock item = items.valueAt(i);
                            stringBuilder.append(item.getValue());
                            stringBuilder.append("\n");
                        }
                        stringBuilder.append('.');
                        txtResult.setText(stringBuilder.toString());

                        str = stringBuilder.toString();
                        Intent myintent = new Intent(Image_Recognition.this, ReminderAddActivity.class);
                        myintent.putExtra("translate", str);
                        startActivity(myintent);

                }
            });
        }
    //}
}

Body:
You have two problems here.

ProgressBar, which you can use ProgressDialog or a ProgressBar in your XML and show it, while hiding the rest of your IU.

Blocking the UI

You are running your loop directly from you click listener, which means that you will block your UI and even if you show some sort of progress, it will be blocked till your loop is over, you need to start a thread and run your loop in.

Here's a not very clean version of you click listener impl

final ProgressDialog dialog = new ProgressDialog(Image_Recognition.this);
        dialog.show();

        new Thread(new Runnable() {
            @Override
            public void run() {
                TextRecognizer textRecognizer = new TextRecognizer.Builder(getApplicationContext()).build();

                Frame frame = new Frame.Builder().setBitmap(bitmap).build();
                SparseArray<TextBlock> items = textRecognizer.detect(frame);
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < items.size(); ++i) {
                    TextBlock item = items.valueAt(i);
                    stringBuilder.append(item.getValue());
                    stringBuilder.append("\n");
                }
                stringBuilder.append('.');
                txtResult.setText(stringBuilder.toString());

                str = stringBuilder.toString();

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        dialog.dismiss();
                        Intent myintent = new Intent(Image_Recognition.this, ReminderAddActivity.class);
                        myintent.putExtra("translate", str);
                        startActivity(myintent);
                    }
                });
            }
        }).start();


问:
Angular response is undefined
Trying to retrieve using angular the json found at: "https://api.github.com/users/angular", more precisely the id property from that json.
Any thoughts on why this fails (in debug mode I get a

'response is not defined'

):

```<code><html ng-app="myViewer">
<head>
<script data-require="angular.js@*" data-semver="1.2.25" src="https://code.angularjs.org/1.2.25/angular.js"></script>
</head>

<body ng-controller="MyController">
    {{ result.id }}
    {{ err }}
</body>

<script type="text/javascript">
(function() {

    var app = angular.module("myViewer", []);

    var MyController = function($scope, $http)
    {
        $http.get("https://api.github.com/users/angular")
        .then(function1, onerr);

        var function1 = function(response)
        {
            $scope.result = response.data;
        }
        var onerr = function(reason)
        {
            $scope.err = "nightmare";
        }

    }

    app.controller("MyController", ["$scope", "$http", MyController]);
}());

</script>
</html>
</code>```

I expect the result to be the id that you can see by copying that link in your browser.

答:
Works if I correct the order:

```<code>var function1 = function(response)
{
    $scope.result = response.data;
}
var onerr = function(reason)
{
    $scope.err = "nightmare";
}

$http.get("https://api.github.com/users/angular")
.then(function1, onerr);
</code>```

function1 should be defined before i call it with then.

Title: Angular response is undefined

Body:
Trying to retrieve using angular the json found at: "https://api.github.com/users/angular", more precisely the id property from that json.
Any thoughts on why this fails (in debug mode I get a

'response is not defined'

):

    {{ result.id }}
    {{ err }}

I expect the result to be the id that you can see by copying that link in your browser.

Body:
Works if I correct the order:

var function1 = function(response)
{
    $scope.result = response.data;
}
var onerr = function(reason)
{
    $scope.err = "nightmare";
}

$http.get("https://api.github.com/users/angular")
.then(function1, onerr);

function1 should be defined before i call it with then.


问:
Using Java, I upload an image to postgres DB size is 4000. But when I download it, the size is 8000
Here is the latest code. I wanted to try something different but I am still getting the same results.

I am using postgres DB and I created a column called file with a data type bytea.
The image does get uploaded to the DB (I can see it in there when I view the table's data).

I tried it with several images. The size appears to be correct when I upload it but then it doubles in size when I download it. (which breaks the image).

Any help on why this is not working is greatly appreciated.

```<code>public void uploadImage(File image, String imageName) throws SQLException {
    try {
        conn = connectionManager.ConnectToDb();

        String sql = "INSERT INTO images (name, file) "+ "VALUES(?,?)";
        System.out.println("your image name is " + imageName);
        System.out.println("Uploaded image name is " + image);

        PreparedStatement stmt = conn.prepareStatement(sql);
        stmt.setString(1,imageName);

        fis = new  FileInputStream(image);
        stmt.setBinaryStream(2, fis, (int) image.length());

        System.out.println("Image SIZE = " +image.length());

        stmt.execute();
        conn.commit();

    } catch (SQLException e) {
        System.out.println("Could not insert into DB");
        e.printStackTrace();
    } catch (FileNotFoundException e) {
            System.out.println("Could not insert into DB");
            e.printStackTrace();
    }
     finally {
        //close DB Objects
        try {
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        conn.close();
    }
}

public void downloadImageFromDB(String imagename) throws SQLException
{
    ConnectionManager connectionManager = new ConnectionManager();

    try {
        conn = connectionManager.ConnectToDb();
        Statement downloadImageStatement = conn.createStatement();
        downloadImageStatement.executeQuery("SELECT file FROM images WHERE name = '"+imagename+"'");
        ResultSet rs = downloadImageStatement.getResultSet();
        int i=1;
        InputStream in = null;
        int returnValue = 0;

        if(rs.next())
        {
            String len1 = rs.getString("file");
            int len = len1.length();
            byte [] b = new byte[len];
            in = rs.getBinaryStream("file");
            int index = in.read(b, 0, len);
            OutputStream outImej = new FileOutputStream("C:\\EclipseProjects\\StrutsHelloWorld\\"+imagename+".JPG");

            while (index != -1)
            {
            outImej.write(b, 0, index);
            index = in.read(b, 0, len);
            System.out.println("==========================");
            System.out.println(index);
            System.out.println(outImej);
            System.out.println("==========================");
            }
            outImej.close();
        }else
            {
            returnValue = 1;
            }

        downloadImageStatement.close();
        conn.close();

    } catch (SQLException e) {
        System.out.println("Could not get image from DB");
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    finally
    {
      // close db objects.
        conn.close();
    }
    //return imgData;
}
</code>```

答: I used the latest version of JDBC driver and the problem was solved. I am using PostgreSQL 9.0.2 and the JDBC4 driver 9.0-801.</p>

Body:
Here is the latest code. I wanted to try something different but I am still getting the same results.

I am using postgres DB and I created a column called file with a data type bytea.
The image does get uploaded to the DB (I can see it in there when I view the table's data).

I tried it with several images. The size appears to be correct when I upload it but then it doubles in size when I download it. (which breaks the image).

Any help on why this is not working is greatly appreciated.

public void uploadImage(File image, String imageName) throws SQLException {
    try {
        conn = connectionManager.ConnectToDb();

        String sql = "INSERT INTO images (name, file) "+ "VALUES(?,?)";
        System.out.println("your image name is " + imageName);
        System.out.println("Uploaded image name is " + image);

        PreparedStatement stmt = conn.prepareStatement(sql);
        stmt.setString(1,imageName);

        fis = new  FileInputStream(image);
        stmt.setBinaryStream(2, fis, (int) image.length());

        System.out.println("Image SIZE = " +image.length());

        stmt.execute();
        conn.commit();

    } catch (SQLException e) {
        System.out.println("Could not insert into DB");
        e.printStackTrace();
    } catch (FileNotFoundException e) {
            System.out.println("Could not insert into DB");
            e.printStackTrace();
    }
     finally {
        //close DB Objects
        try {
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        conn.close();
    }
}

public void downloadImageFromDB(String imagename) throws SQLException
{
    ConnectionManager connectionManager = new ConnectionManager();

    try {
        conn = connectionManager.ConnectToDb();
        Statement downloadImageStatement = conn.createStatement();
        downloadImageStatement.executeQuery("SELECT file FROM images WHERE name = '"+imagename+"'");
        ResultSet rs = downloadImageStatement.getResultSet();
        int i=1;
        InputStream in = null;
        int returnValue = 0;

        if(rs.next())
        {
            String len1 = rs.getString("file");
            int len = len1.length();
            byte [] b = new byte[len];
            in = rs.getBinaryStream("file");
            int index = in.read(b, 0, len);
            OutputStream outImej = new FileOutputStream("C:\\EclipseProjects\\StrutsHelloWorld\\"+imagename+".JPG");

            while (index != -1)
            {
            outImej.write(b, 0, index);
            index = in.read(b, 0, len);
            System.out.println("==========================");
            System.out.println(index);
            System.out.println(outImej);
            System.out.println("==========================");
            }
            outImej.close();
        }else
            {
            returnValue = 1;
            }

        downloadImageStatement.close();
        conn.close();

    } catch (SQLException e) {
        System.out.println("Could not get image from DB");
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    finally
    {
      // close db objects.
        conn.close();
    }
    //return imgData;
}


问:
How to get content from DynamicAssembly object?
So i have a dynamic object with some lists inside of it like this:

```<code>ob
 data
  [0]
    List one
      [...]
  [1]
    List two
      [...]
</code>```

I can't recover the values from the lists, i'm stuck at the data level, i already try this:

```<code>  object valor = t3.GetProperty("data").GetValue(ob, null);
</code>```

And i got one object with this structure:

```<code>valor
  [0]
    List one
      [...]
  [1]
    List two
      [...]
</code>```

How can i get inside the lists inside of it?
Sorry about the question, but i already spend some hours searching example's of consuming data from objects and nothings seems to work.

答:
I figure it out with this simples code:

```<code>object ob = MyObject;
string datalevel = TheLevelIWant;
                        var data = ob.GetType().GetProperty("data").GetValue(ob);

                        if (data.GetType().IsGenericType)
                        {
                            foreach(object obj in (data as IEnumerable).Cast<object>().ToList())
                            {
                                ob = obj.GetType().GetProperty(datalevel);
                            }
                        }
</code>```

With this code i have to search in every level for the fields that i want to get the values from.
Just need to add recursive method to do this.

Body:
So i have a dynamic object with some lists inside of it like this:

ob
 data
  [0]
    List one
      [...]
  [1]
    List two
      [...]

I can't recover the values from the lists, i'm stuck at the data level, i already try this:

  object valor = t3.GetProperty("data").GetValue(ob, null);

And i got one object with this structure:

valor
  [0]
    List one
      [...]
  [1]
    List two
      [...]

How can i get inside the lists inside of it?
Sorry about the question, but i already spend some hours searching example's of consuming data from objects and nothings seems to work.

Body:
I figure it out with this simples code:

object ob = MyObject;
string datalevel = TheLevelIWant;
                        var data = ob.GetType().GetProperty("data").GetValue(ob);

                        if (data.GetType().IsGenericType)
                        {
                            foreach(object obj in (data as IEnumerable).Cast<object>().ToList())
                            {
                                ob = obj.GetType().GetProperty(datalevel);
                            }
                        }

With this code i have to search in every level for the fields that i want to get the values from.
Just need to add recursive method to do this.


问:
Having an issue with order of operations in node.js function
I have a function that's I would like to use to poll historical data beginning from the start of Ethereum trading on the gdax exchange to current.  I want the code to poll 100 results (max allowable at a time) insert results into mongodb, add 100, then repeat, until I've got all historical data.  However, what I've wrote is executing in a different order.  First it sums all numbers in the for next, then executes all the http authedclient requests (although it properly uses the variable adding 100 to each request), then drops all the data into mongodb.  The problem I'm having is by the time the data is inserted into the mongodb client, the connection is closed.  How can I get it to execute each operation in the order I want it to?  Pastebin posted below.  Note the code I use has changed significantly to accommodate other errors, changed the insert loop to insertMany but I can integrate suggestions properly if anyone can help.  Thanks in advance.

https://pastebin.com/1BHi9RQV

```<code>var i = 100;

for (; i < 18750000; ) {

    publicClient.getProductTrades({ after: i }, function (err, response, data) {

        if (err) {

            console.log(err);

            return;

        }

        MongoClient.connect(url, function (err, db) {

            if (err) {

                console.log(err);

                return;

            }

            var myobj = { data };

            for (item in data) {

                db.collection("EthTest").insertOne(data[item], function (err, res) {

                    if (err) {

                        console.log(err);

                        return;

                    }

                });

                console.log(data[item].trade_id);

            }

            db.close();

        });

    });

    i = i + 100;

};
</code>```

Also downloaded stack app to properly post link and code.  Mobile site didn't allow me to do that.  Sorry!

答:
Don't put db.close(); in your for loop. Only call it once all your inserts are completed.

If this order is really important (get 100 results, store them, and so on), I suggest you split this code in 2 functions that call each other.
Something like that:

```<code>var i = 100;
var mongo;

function getData() {
    publicClient.getProductTrades({ after: i }, function (err, response, data) {
        if (err) {
            console.log(err);
            return;
        }

        i = i + 100;
        saveData(data);
    });
}

function saveData(data) {

    var keys = Object.keys(data);

    // loop through the data
    for (j = 0, end = keys.length; j < end; j++) {
        db.collection("EthTest").insertOne(data[item], function (err, res) {
            if (err) {
                console.log(err);
                return;
            }

            console.log(data[item].trade_id);

            if (keys[j] === keys[keys.length-1]) {
                // last item in data was inserted
                if (i < 18750000) {
                    // get the next 100 results if there's any
                    getData();
                } else {
                    mongo.close();
                }
            }
        });
    };
}

MongoClient.connect(url, function (err, db) {
    if (err) {
        console.log(err);
        return;
    }

    mongo = db;
    getData();
});
</code>```

Or course I cannot test it for you, but I hope you get the idea.

The other option would be to separate your 2 async calls.
Have the first loop get all the data (100 at a time), store them in an array, and once that is done, loop through that array and insert the data in Mongo.

Body:
I have a function that's I would like to use to poll historical data beginning from the start of Ethereum trading on the gdax exchange to current.  I want the code to poll 100 results (max allowable at a time) insert results into mongodb, add 100, then repeat, until I've got all historical data.  However, what I've wrote is executing in a different order.  First it sums all numbers in the for next, then executes all the http authedclient requests (although it properly uses the variable adding 100 to each request), then drops all the data into mongodb.  The problem I'm having is by the time the data is inserted into the mongodb client, the connection is closed.  How can I get it to execute each operation in the order I want it to?  Pastebin posted below.  Note the code I use has changed significantly to accommodate other errors, changed the insert loop to insertMany but I can integrate suggestions properly if anyone can help.  Thanks in advance.

https://pastebin.com/1BHi9RQV

var i = 100;

for (; i < 18750000; ) {

    publicClient.getProductTrades({ after: i }, function (err, response, data) {

        if (err) {

            console.log(err);

            return;

        }

        MongoClient.connect(url, function (err, db) {

            if (err) {

                console.log(err);

                return;

            }

            var myobj = { data };

            for (item in data) {

                db.collection("EthTest").insertOne(data[item], function (err, res) {

                    if (err) {

                        console.log(err);

                        return;

                    }

                });

                console.log(data[item].trade_id);

            }

            db.close();

        });

    });

    i = i + 100;

};

Also downloaded stack app to properly post link and code.  Mobile site didn't allow me to do that.  Sorry!

Body:
Don't put db.close(); in your for loop. Only call it once all your inserts are completed.

If this order is really important (get 100 results, store them, and so on), I suggest you split this code in 2 functions that call each other.
Something like that:

var i = 100;
var mongo;

function getData() {
    publicClient.getProductTrades({ after: i }, function (err, response, data) {
        if (err) {
            console.log(err);
            return;
        }

        i = i + 100;
        saveData(data);
    });
}

function saveData(data) {

    var keys = Object.keys(data);

    // loop through the data
    for (j = 0, end = keys.length; j < end; j++) {
        db.collection("EthTest").insertOne(data[item], function (err, res) {
            if (err) {
                console.log(err);
                return;
            }

            console.log(data[item].trade_id);

            if (keys[j] === keys[keys.length-1]) {
                // last item in data was inserted
                if (i < 18750000) {
                    // get the next 100 results if there's any
                    getData();
                } else {
                    mongo.close();
                }
            }
        });
    };
}

MongoClient.connect(url, function (err, db) {
    if (err) {
        console.log(err);
        return;
    }

    mongo = db;
    getData();
});

Or course I cannot test it for you, but I hope you get the idea.

The other option would be to separate your 2 async calls.
Have the first loop get all the data (100 at a time), store them in an array, and once that is done, loop through that array and insert the data in Mongo.


问:
Using PhraseMatcher in SpaCy to find multiple match types
The SpaCy documentation and samples show that the PhraseMatcher class is useful to match sequences of tokens in documents. One must provide a vocabulary of sequences that will be matched.

In my application, I have documents that are collections of tokens and phrases. There are entities of different types. The data is remotely natural language (documents are rather set of keywords with semi-random order). I am trying to find matches of multiple types.

For example:

```<code>yellow boots for kids
</code>```

How can I find the matches for colors (e.g. yellow), for product types (e.g. boots) and for the age (e.g. kids) using SpaCy's PhraseMatches? Is this a good use case? If the different entity matches overlap (e.g. color is matched in colors list and in materials list), is it possible to produce all unique cases?

I cannot really use a sequence tagger as the data is loosely structured and is riddled with ambiguities. I have a list of entities (e.g. colors, ager, product types) and associated value lists.

One idea would be to instantiate multiple PhraseMatcher objects, one for each entity, do the matches separately and then merge the results. Each entity type will get its own vocabulary. This sounds straightforward but can be not efficient, especially the merging part. The value lists are fairly large. Before going this route, I would like to know if this is a good idea or perhaps there are simpler ways to do that with SpaCy.

答:
spaCy's PhraseMatcher supports adding multiple rules containing several patterns, and assigning IDs to each matcher rule you add. If two rules overlap, both matches will be returned. So you could do something like this:

```<code>color_patterns = [nlp(text) for text in ('red', 'green', 'yellow')]
product_patterns = [nlp(text) for text in ('boots', 'coats', 'bag')]
material_patterns = [nlp(text) for text in ('silk', 'yellow fabric')]

matcher = PhraseMatcher(nlp.vocab)
matcher.add('COLOR', None, *color_patterns)
matcher.add('PRODUCT', None, *product_patterns)
matcher.add('MATERIAL', None, *material_patterns)
</code>```

When you call the matcher on your doc, spaCy will return a list of (match_id, start, end) tuples. Because spaCy stores all strings as integers, the match_id you get back will be an integer, too – but you can always get the string representation by looking it up in the vocabulary's StringStore, i.e. nlp.vocab.strings:

```<code>doc = nlp("yellow fabric")
matches = matcher(doc)
for match_id, start, end in matches:
    rule_id = nlp.vocab.strings[match_id]  # get the unicode ID, i.e. 'COLOR'
    span = doc[start : end]  # get the matched slice of the doc
    print(rule_id, span.text)

# COLOR yellow
# MATERIAL yellow fabric
</code>```

When you add matcher rules, you can also define an on_match callback function as the second argument of Matcher.add. This is often useful if you want to trigger specific actions – for example, do one thing if a COLOR match is found, and something else for a PRODUCT match.

If you want to solve this even more elegantly, you might also want to look into combining your matcher with a custom pipeline component or custom attributes. For example, you could write a simple component that's run automatically when you call nlp() on your text, finds the matches, and sets a Doc._.contains_product or Token._.is_color attribute. The docs have a few examples of this that should help you get started.

Body:
The SpaCy documentation and samples show that the PhraseMatcher class is useful to match sequences of tokens in documents. One must provide a vocabulary of sequences that will be matched.

In my application, I have documents that are collections of tokens and phrases. There are entities of different types. The data is remotely natural language (documents are rather set of keywords with semi-random order). I am trying to find matches of multiple types.

For example:

yellow boots for kids

How can I find the matches for colors (e.g. yellow), for product types (e.g. boots) and for the age (e.g. kids) using SpaCy's PhraseMatches? Is this a good use case? If the different entity matches overlap (e.g. color is matched in colors list and in materials list), is it possible to produce all unique cases?

I cannot really use a sequence tagger as the data is loosely structured and is riddled with ambiguities. I have a list of entities (e.g. colors, ager, product types) and associated value lists.

One idea would be to instantiate multiple PhraseMatcher objects, one for each entity, do the matches separately and then merge the results. Each entity type will get its own vocabulary. This sounds straightforward but can be not efficient, especially the merging part. The value lists are fairly large. Before going this route, I would like to know if this is a good idea or perhaps there are simpler ways to do that with SpaCy.

Body:
spaCy's PhraseMatcher supports adding multiple rules containing several patterns, and assigning IDs to each matcher rule you add. If two rules overlap, both matches will be returned. So you could do something like this:

color_patterns = [nlp(text) for text in ('red', 'green', 'yellow')]
product_patterns = [nlp(text) for text in ('boots', 'coats', 'bag')]
material_patterns = [nlp(text) for text in ('silk', 'yellow fabric')]

matcher = PhraseMatcher(nlp.vocab)
matcher.add('COLOR', None, *color_patterns)
matcher.add('PRODUCT', None, *product_patterns)
matcher.add('MATERIAL', None, *material_patterns)

When you call the matcher on your doc, spaCy will return a list of (match_id, start, end) tuples. Because spaCy stores all strings as integers, the match_id you get back will be an integer, too – but you can always get the string representation by looking it up in the vocabulary's StringStore, i.e. nlp.vocab.strings:

doc = nlp("yellow fabric")
matches = matcher(doc)
for match_id, start, end in matches:
    rule_id = nlp.vocab.strings[match_id]  # get the unicode ID, i.e. 'COLOR'
    span = doc[start : end]  # get the matched slice of the doc
    print(rule_id, span.text)

# COLOR yellow
# MATERIAL yellow fabric

When you add matcher rules, you can also define an on_match callback function as the second argument of Matcher.add. This is often useful if you want to trigger specific actions – for example, do one thing if a COLOR match is found, and something else for a PRODUCT match.

If you want to solve this even more elegantly, you might also want to look into combining your matcher with a custom pipeline component or custom attributes. For example, you could write a simple component that's run automatically when you call nlp() on your text, finds the matches, and sets a Doc._.contains_product or Token._.is_color attribute. The docs have a few examples of this that should help you get started.


问:
log4j2 unlimited RollingFile
I'm using log4j2 and trying to log with log-rotation. Specifically, I want to log at the maximum size of 10MB and rotate unlimitedly. The configuration below generates 3 generations of rolling files because "DefaultRolloverStrategy max" is set to 3. Could you please, guide me how to log unlimited number of files with at the maximum size of 10MB? </p>

```<code><?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
    <Properties>
        <Property name="format1">%m%n</Property>
        <Property name="logfile">${sys:logDirectory}/log.log</Property>
        <Property name="logfile-archive">${sys:logDirectory}/log_%d{yyyy-MM-dd}.%i.log
        </Property>
    </Properties>
    <Appenders>
        <RollingFile name="logfile001" append="true" fileName="${logfile}"
            filePattern="${logfile-archive}">
            <PatternLayout>
                <pattern>${format1}</pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="10MB" />
            </Policies>
            <DefaultRolloverStrategy max="3" />
        </RollingFile>
    </Appenders>

    <Loggers>
        <Root level="trace">
            <AppenderRef ref="logfile001" />
        </Root>
    </Loggers>
</Configuration>
</code>```

答:
Set an extreme value to DefaultRolloverStrategy max. E.g.

```<code><DefaultRolloverStrategy max="1000000000" />
</code>```

Update:

According to Log4j2 documentation, as of release 2.8, it can be done by setting fileIndex attribute to nomax. E.g.

```<code><DefaultRolloverStrategy fileIndex="nomax" />
</code>```

Title: log4j2 unlimited RollingFile

Body:
I'm using log4j2 and trying to log with log-rotation. Specifically, I want to log at the maximum size of 10MB and rotate unlimitedly. The configuration below generates 3 generations of rolling files because "DefaultRolloverStrategy max" is set to 3. Could you please, guide me how to log unlimited number of files with at the maximum size of 10MB?

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
    <Properties>
        <Property name="format1">%m%n</Property>
        <Property name="logfile">${sys:logDirectory}/log.log</Property>
        <Property name="logfile-archive">${sys:logDirectory}/log_%d{yyyy-MM-dd}.%i.log
        </Property>
    </Properties>
    <Appenders>
        <RollingFile name="logfile001" append="true" fileName="${logfile}"
            filePattern="${logfile-archive}">
            <PatternLayout>
                <pattern>${format1}</pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="10MB" />
            </Policies>
            <DefaultRolloverStrategy max="3" />
        </RollingFile>
    </Appenders>

    <Loggers>
        <Root level="trace">
            <AppenderRef ref="logfile001" />
        </Root>
    </Loggers>
</Configuration>

Body:
Set an extreme value to DefaultRolloverStrategy max. E.g.

<DefaultRolloverStrategy max="1000000000" />

Update:

According to Log4j2 documentation, as of release 2.8, it can be done by setting fileIndex attribute to nomax. E.g.

<DefaultRolloverStrategy fileIndex="nomax" />