Should we carry Tags in Titles?

Question: I'd like to know what the community thinks on this topic for this very site.
Should the tags (e.g., country-specific ones) exist within question titles, or they have to be avoided for sake of clarity?
It has been discussed before:
Should questions include "tags" in their titles?
How do I write a good title?
See this edit for example — not that I disagree, but for me it would be nice to know the policy and avoid further mistakes.
Answer: The system will automatically join popular tags to the left side of the title in the rendered HTML <title></title> element - this is done specifically for SEO and delivering more useful titles in search engine result listings.
It's therefore good to avoid deliberately adding tag words in titles, but don't break good composition purely for the sake of avoiding or including one. Here's an example:

How do I tell if a taxi turned on its meter in The Philippines?

That's obviously going to have philippines attached to it, and reiterated in the title, but it's a good title.

Philippines: How do I know if a taxi turned on its meter?

.. That's bad. You're just duplicating what the engine selectively does, and it does a very good job of picking the right tag to join in the title.

How do I know if a taxi turned on its meter?

.. Also bad, because depending on how folks read, they don't know if it's a question they can or can't answer.

How do I know if a taxi turned on its meter in Manila?

Along with philippines - that's the best combination. Get to the specific point as quickly as you can, you've avoided tags in titles, and now there's two locations associated with your question.
In short, don't write for SEO - let the system do it, just write titles that grab the attention of the folks likely to be able to answer the question.
Comment: Great answer, thanks. The last idea sounds most reasonable. The problem is that not every SE user is familiar with SEO techniques... :)

Should we carry Tags in Titles?


How can I convert days into weeks and days

Question: I have a date range say 1-Jul-2016 to 10-Jul-2016. I want to extract number of weeks and remaining days exists in that range like
No. of Weeks = 1
No. of Remaining Days = 3
So for this case the answer i want to see is 1.3
I know how to find days OR week difference using
DATEDIFF(DAY,@ArrivalDate,@DepartureDate)
DATEDIFF(WEEK,@ArrivalDate,@DepartureDate)

But how to find and get whether a date contains only full Weeks or Weeks and Days.
Any help will be highly appreciated.
Comment: Simply  `floor(Days/7,0)` to get your weeks and use `mod(Days,7)` to get days remainder  functions may vary slightly based on RDBMS but you'd need to tag the question with what database & version you're on to help much further.   (Substitute your datediff formula for Days in the above
Comment: thank you for your suggestion , it's tsql is the database i use
Comment: Which limits it to SQL Server and Sybase I believe.  Still don't know version.  Now with regards to "how it contains full weeks... How do we know what Day of week your week starts on or do we just count 7 consecutive days as a "Week"?  so lets say we start on Tuesday and wrap around a full week + 2 days to thursday  Would that be 0 weeks and 9 days or 1 week 2 days?
Comment: we just 7 consecutive days as a week, actually i want to use this for age so it doesnt matter what is the week start
Comment: thanks for the answer i'll and let you know the result.
Answer: Example:

(Days/7) as weeks  (Get a int result so it's always a whole number)
Modulus (Days % 7 as days)  (gets you the remainder days of a week)

.
SELECT datediff(DAY,@ArrivalDate,@Departure) / 7 as weeks
     , datediff(DAY,@ArrivalDate,@Departure) % 7 as days

DEMO
Comment: as such, the approach of going to a finer level of precision (day) and dividing is advisable, though note that it can still technically give rise to an error in that Sunday 1st at 23:59:59 to Sunday 8th 00:00:01 is technically only 6 days and 2 seconds, but datediff reports it as 7 days because the "midnight" date boundary has been crossed over 7 times.. Depending on the precision required, one might choose to `datediff(second, …)/86400` etc
Comment: I tend to think of date math related questions in the oracle sense, where end date minus start date is a float number of days, and a day is 24h or 86400 seconds etc - 6am Sunday minus 6pm Saturday is half a day. Though I wish it werent thus, datediff inaccuracy tends not to matter so long as you're aware of it and adjust solutions accordingly.
Comment: Ah true. modified answer/demo
Comment: Side note: datediff does also take a WK specifier to give the number of weeks between two dates, but it's afflicted somewhat by the typical datediff problem that it doesn't give the number of weeks between two dates, it gives the count of times the week boundary (midnight sunday) is crossed, so `select datediff(wk,'20170107','20170108')` which is Saturday to Sunday gives a result as "1 week" when it's actually only one day..
Comment: @CaiusJard  isn't that always the case?  how precise?  "What denotes a "Day" 24 hours or crossing a timezones midnight boundary?  How do we know that arrivaldate and departure date are in the same timezone?  I love date/time questions.   I just went with the basics and said a any time w/in a new "date" boundary was considered 1. As with many questions/problems answers are only as precise as the definitions given for the words used ;P  Lets add in leap years and leapseconds to boot!\


asyncio.sleep(0) does not yield control to the event loop

Question: I have a simple async setup which includes two coroutines: light_job and heavy_job. light_job halts in the middle and heavy_job starts. I want heavy_job to yield the control in the middle and allow light_job to finish but asyncio.sleep(0) is not working as I expect.
this is the setup:
import asyncio
import time

loop = asyncio.get_event_loop()

async def light_job():
    print("hello ")
    print(time.time())
    await asyncio.sleep(1)
    print(time.time())
    print("world!")

async def heavy_job():
    print("heavy start")
    time.sleep(3)
    print("heavy halt started")
    await asyncio.sleep(0)
    print("heavy halt ended")
    time.sleep(3)
    print("heavy done")

loop.run_until_complete(asyncio.gather(
    light_job(),
    heavy_job()
))

if I run this code, the light_job will not continue until after heavy_job is done. this is the outpu:
hello
1668793123.159075
haevy start
heavy halt started
heavy halt ended
heavy done
1668793129.1706061
world!

but if I change asyncio.sleep(0) to asyncio.sleep(0.0001), the code will work as expected:
hello
1668793379.599066
heavy start
heavy halt started
1668793382.605899
world!
heavy halt ended
heavy done

based on documentations and related threads, I expect asyncio.sleep(0) to work exactly as asyncio.sleep(0.0001). what is off here?
Comment: `time.sleep(3)` will put to sleep the whole program, so nothing else is executed. `asyncio` is not to meant to execute CPU bound tasks - for that use threads or `multiprocessing`
Comment: I'm using time.sleep on purpose (for simulating a cpu-demanding task). my question is why the asyncio.sleep(0) (between two time.sleeps) does not yield the control whereas asyncio.sleep(0.0..01) does.
Comment: as I said, I'm doing that on purpose. I want heavy_job to keep control for 3 seconds(time.sleep), than pass it to light_job (asyncio.sleep) and then keep it again for 3 seconds(time.sleep). it does so when I use asyncio.sleep(0.0001), but not when I use asyncio.sleep(0). my question is about the difference between these two.
Comment: There's a difference in how they're handled in the asyncio internal code, but every piece of documentation, forum thread, SO question, etc. I can find seems to be telling me they're supposed to act the same in the end. I can reproduce the results you're seeing; no idea why.
Comment: Because when you run `time.sleep(3)` the whole script is put asleep and `await asyncio.sleep(0)` is executed only after 3 seconds have passed.
Answer: I think this subject needs some more discussion.  I intend this post as an appendix to Daniel T's excellent and very clever answer - that's a fine piece of work.  But Dan Getz's comment made me think that some more detail would be helpful.
Dan suggests that there is no general way to yield to another task.  This is correct because there is no guarantee that any other Task is ready to run, nor is there any guarantee of the execution order of the various Tasks.  The example program fails to meet expectations because of details in the event loop implementation, which I discuss below.
There are, however, tools for unambiguously synchronizing work between different Tasks. It's probably a bad idea to rely on time intervals in asyncio.sleep() for this purpose.  Consider the following program, which uses an asyncio.Event to force light_job() to finish before heavy_job() can enter its second time.sleep delay.  This will always work because the program logic is explicit:
import asyncio
import time

event = asyncio.Event()

async def light_job():
    print("hello ")
    print(time.time())
    await asyncio.sleep(1)
    print(time.time())
    print("world!")
    event.set()

async def heavy_job():
    print("heavy start")
    time.sleep(3)
    print("heavy halt started")
    # await asyncio.sleep(0)
    await event.wait()
    print("heavy halt ended")
    time.sleep(3)
    print("heavy done")

async def main():
    await asyncio.gather(light_job(), heavy_job())

asyncio.run(main())

Even simpler is this approach, which avoids the use of Event and even of gather:
import asyncio
import time

async def light_job():
    print("hello ")
    print(time.time())
    await asyncio.sleep(1)
    print(time.time())
    print("world!")

async def heavy_job():
    light = asyncio.create_task(light_job())
    print("heavy start")
    time.sleep(3)
    print("heavy halt started")
    # await asyncio.sleep(0)
    await light
    print("heavy halt ended")
    time.sleep(3)
    print("heavy done")

async def main():
    await heavy_job()

asyncio.run(main())

As for why the original script failed, the explanation can be found in the event loop implementation.  An event loop keeps track of two things: a list of "ready" items, representing Tasks that are able to execute right now; and a list of "scheduled" items, representing Tasks that are waiting for some time interval to expire.
Every time the event loop goes through a cycle, its first step is to examine the list of scheduled items and see if any are ready to proceed.  It appends any of those items to the "ready" list.  Then it executes this simple loop to run all the ready Tasks (I have omitted some diagnostic code; this is from Python3.10 standard library module base_events.py).  Here, _ready is a deque.  The items in the queue all have a run method that causes the Task to take one step forward, or in other words, to resume the Task at the point where it previously was suspended (typically an await expression).
    ntodo = len(self._ready)
    for i in range(ntodo):
        handle = self._ready.popleft()
        if handle._cancelled:
            continue
        else:
            handle._run()

It's also the case that await asyncio.sleep(0) is implemented differently from await asyncio.sleep(x) where x > 0.  In the first case, the await expression yields a value of None.  The Task object simply appends an item to the "ready" list.  In the second case, the await expression executes a loop.call_later function call, which creates a Future. The Task object appends an item to the "scheduled" list. Here is the implementation of asyncio.sleep in tasks.py:
@types.coroutine
def __sleep0():
    """Skip one event loop run cycle.

    This is a private helper for 'asyncio.sleep()', used
    when the 'delay' is set to 0.  It uses a bare 'yield'
    expression (which Task.__step knows how to handle)
    instead of creating a Future object.
    """
    yield

async def sleep(delay, result=None):
    """Coroutine that completes after a given time (in seconds)."""
    if delay <= 0:
        await __sleep0()
        return result

    loop = events.get_running_loop()
    future = loop.create_future()
    h = loop.call_later(delay,
                        futures._set_result_unless_cancelled,
                        future, result)
    try:
        return await future
    finally:
        h.cancel()

So in the example script in the original post, the Task test will start with two items in its "ready" list: [light_job, heavy_job].  The scheduled list is empty.  Light_job starts and hits await asyncio.sleep(1), so an item is appended to the "scheduled" list that represents this time delay.  Now heavy_job runs for three seconds and hits await asyncio.sleep(0), so an item is appended to the "ready" list which indicates that this Task is to proceed without delay.  That's the end of one full cycle of the event loop.  The cycle ends even though the ready list isn't empty at that point, because the await with a zero delay caused heavy_job to be appended to the ready list immediately.
In the next cycle of the event loop, the ready list has one item, which was placed there on the previous cycle: [heavy_job].  The scheduled list also has one item: [light_job].  The event loop examines the scheduled list and sees that light_job is now ready, so it appends light_job to ready_list, which now looks like this: [heavy_job, light_job].  So the code logic has essentially caused the order of the Tasks to get switched.  Result: heavy_job runs twice in a row, once at the end of the first cycle and once at the beginning of the second.
This also explains what happened when you replaced await asyncio.sleep(0) with await asyncio.sleep(0.0001).  In that case, the Task got appended to the scheduled list rather than the ready list.  Then ready=[] and scheduled=[light_job, heavy_job].  On the next cycle of the loop both Tasks are ready, but the order will once again be [light_job, heavy_job].
This machinery is invisible to client code, as it should be, but it has a weird consequence in this particular script.  Whether or not this should be called a "bug" is a matter of debate.  I assume there are good performance reasons why asyncio.sleep(0) is implemented differently from asyncio.sleep(nonzero).
Comment: _There are, however, tools for unambiguously synchronizing work between different Tasks. It's probably a bad idea to rely on time intervals in `asyncio.sleep()` for this purpose._ Indeed, if one just wants to ensure the 'light-heavy-light-heavy' handshake without delays, the simplest approach is to call `asyncio.sleep(0)` in `light_job`. If the OP concern is how to ensure that an `asyncio.sleep`ing job is executed ASAP when the delay has expired, then probably this is impossible. Timely execution of tasks in an async framework relies on the assumption that no task will hijack the event loop.
Comment: A better usecase is as follows: I have a compute heavy longrunning task that is easily broken up internally into multiple short - but still compute-heavy - sections. For instance, doing many iterations of a dataprocessing loop. I find that this task is starving everything. What do I do? In 'most' async frameworks, you can just drop in an explicit yield point and things 'just work'. In Python... about the best way is the `await asyncio.sleep(0.0001)` hack so far as I can tell.
Comment: Sometimes you can move said compute-heavy task to a background _process_ - but this often requires architectural changes (e.g. if said task uses data that is not pickleable.)
Comment: Though note that it really should be e.g. `await asyncio.sleep(1e-200)` or somesuch, not `0.0001`. Any positive value works - but there are cases where sleeping 0.1ms still adds up to a fair bit.
Comment: @TLW The asyncio event loop has a timing granularity, given by `time.get_clock_info('monotonic').resolution`.  On my machine (Windows10, Python3.11) this is 0.015625 seconds.  So there is no difference between asyncio.sleep(0.01) and asyncio.sleep(1e-200); both numbers are > 0.0 but < 0.015625.  Furthermore, nothing is actually "sleeping" during an asyncio.sleep, as long as there is another task that can run.  No time is consumed beyond that required for a task switch.
Comment: @PaulCornelius - only on Windows. On my (Linux) machine `time.get_clock_info('monotonic').resolution` is `1e-9`. As I mentioned above the main usecase for this is a `yield` in a compute task. Say the task does ten thousand iterations that each take ~1ms. With no yields, this completes in ~10s but blocks everything. With a sub-resolution yield, and nothing else taking significant time, this completes in ~10s (+ yield overhead). With a yield of 0.01 seconds, and nothing else taking significant time, this completes in... 110s (+ yield overhead). Oops!
Comment: Well of course you should use a value that is less than your system's timing resolution.  What I don't understand is why you don't simply use asyncio.sleep(0.0).  That will always take a minimal amount of time unless there is another task waiting to run.  The original question, and my answer, does not imply that asyncio.sleep(0) always fails to yield to the event loop.  In fact in normal cases, and perhaps all cases of practical interest, asyncio.sleep(0) does yield to the loop and is what should be used.
Comment: See the [other](https://stackoverflow.com/a/74498442/1814881) answer for why `asyncio.sleep(0)` does not work in many cases.
Comment: "Well of course you should use a value that is less than your system's timing resolution.". Exactly. My point is that `0.0001` is not a good 'default' value to pick, because on many systems it fails to satisfy said criteria.
Comment: @TLW I think you have misinterpreted the other answer.  It does not show that asyncio.sleep(0) should not be used "in many cases," in fact it does not show any case where it should not be used.  `asyncio.sleep(x)` for small x creates a Future, appends that Future to the waiting list, and cycles once through the waiting tasks.  If there are no waiting tasks, yours resumes.  `asyncio.sleep(0)` yields to the event loop immediately, and if there is no pending task then execution continues.  Can you describe a situation where this causes a problem?
Comment: Note on history: asyncio.sleep(0) was implemented in 2015, in [PR #285](https://github.com/python/asyncio/pull/285). Thanks for a nice answer!
Answer: Call asyncio.sleep(0) 3 times:
import asyncio
import time

async def light_job():
    print("hello ")
    print(time.time())
    await asyncio.sleep(1)
    print(time.time())
    print("world!")

async def heavy_job():
    print("heavy start")
    time.sleep(3)
    print("heavy halt started")
    for _ in range(3):
        await asyncio.sleep(0)
    print("heavy halt ended")
    time.sleep(3)
    print("heavy done")

async def test():
    await asyncio.gather(
        light_job(),
        heavy_job()
    )

asyncio.run(test())

This results in:
hello
1668844526.157173
heavy start
heavy halt started
1668844529.1575627
world!
heavy halt ended
heavy done

Looking at "asyncio/base_events.py", "_run_once" goes over pending timers first then runs everything it sees after calculating that. asyncio.sleep can only skip one iteration of the event loop. Multiple sleeps are required because asyncio.sleep(1) schedules a future which takes one extra iteration before giving back control to light_job by adding light_job back to the queue, and asyncio happens to run newly queued jobs last.
For a clearer picture, it is possible to add more print statements:
import asyncio
import time

async def light_job():
    print("hello ")
    print(time.time())
    await asyncio.sleep(1)
    print(time.time())
    print("world!")

async def heavy_job():
    print("heavy start")
    time.sleep(3)
    print("heavy halt started")
    # Sleep to yield to the event loop. light_job isn't detected as ready so this iteration of the loop will finish
    await asyncio.sleep(0)

    print("after 1 sleep")
    # We are still in front of the event loop. Yield so that the 1 second timer in light_job runs.
    # The timer will realize it itself has expired, then put light_job back onto the queue.
    await asyncio.sleep(0)

    # Again the current Python implementation puts us in front. Yield so that the light_job runs
    print("after 2 sleeps")
    await asyncio.sleep(0)

    print("heavy halt ended")
    time.sleep(3)
    print("heavy done")

async def test():
    await asyncio.gather(
        light_job(),
        heavy_job()
    )

asyncio.run(test())

Then add breakpoints in "def _run_once(self):" of "asyncio/base_events.py". Add a breakpoint printing "loop start" on line 1842 at the start a.k.a "sched_count =". Add another one at line 1910 at the end a.k.a "handle = None" printing "loop end". Then add one before each task is run on line 1897 a.k.a "if self._debug:" evaluating and printing "_format_handle(handle)". The sequence of events is revealed:
loop start
<Task pending name='Task-1' coro=<test() running at /home/home/PycharmProjects/sandbox/notsync.py:34> cb=[_run_until_complete_cb() at /usr/lib/python3.11/asyncio/base_events.py:180]>
loop end
loop start
<Task pending name='Task-2' coro=<light_job() running at /home/home/PycharmProjects/sandbox/notsync.py:5> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
hello
1668844827.5052986
<Task pending name='Task-3' coro=<heavy_job() running at /home/home/PycharmProjects/sandbox/notsync.py:13> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
heavy start
heavy halt started
loop end
loop start
<Task pending name='Task-3' coro=<heavy_job() running at /home/home/PycharmProjects/sandbox/notsync.py:18> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
after 1 sleep
<TimerHandle when=37442.097934711 _set_result_unless_cancelled(<Future pendi...ask_wakeup()]>, None) at /usr/lib/python3.11/asyncio/futures.py:317>
loop end
loop start
<Task pending name='Task-3' coro=<heavy_job() running at /home/home/PycharmProjects/sandbox/notsync.py:23> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
after 2 sleeps
<Task pending name='Task-2' coro=<light_job() running at /home/home/PycharmProjects/sandbox/notsync.py:8> wait_for=<Future finished result=None> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
1668844830.9250844
world!
loop end
loop start
<Task pending name='Task-3' coro=<heavy_job() running at /home/home/PycharmProjects/sandbox/notsync.py:27> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
heavy halt ended
heavy done
<Handle gather.<locals>._done_callback(<Task finishe...> result=None>) at /usr/lib/python3.11/asyncio/tasks.py:759>
loop end
loop start
<Handle gather.<locals>._done_callback(<Task finishe...> result=None>) at /usr/lib/python3.11/asyncio/tasks.py:759>
loop end
loop start
<Task pending name='Task-1' coro=<test() running at /home/home/PycharmProjects/sandbox/notsync.py:35> wait_for=<_GatheringFuture finished result=[None, None]> cb=[_run_until_complete_cb() at /usr/lib/python3.11/asyncio/base_events.py:180]>
loop end
loop start
<Handle _run_until_complete_cb(<Task finishe...> result=None>) at /usr/lib/python3.11/asyncio/base_events.py:180>
loop end
loop start
<Task pending name='Task-4' coro=<BaseEventLoop.shutdown_asyncgens() running at /usr/lib/python3.11/asyncio/base_events.py:539> cb=[_run_until_complete_cb() at /usr/lib/python3.11/asyncio/base_events.py:180]>
loop end
loop start
<Handle _run_until_complete_cb(<Task finishe...> result=None>) at /usr/lib/python3.11/asyncio/base_events.py:180>
loop end
loop start
<Task pending name='Task-5' coro=<BaseEventLoop.shutdown_default_executor() running at /usr/lib/python3.11/asyncio/base_events.py:564> cb=[_run_until_complete_cb() at /usr/lib/python3.11/asyncio/base_events.py:180]>
loop end
loop start
<Handle _run_until_complete_cb(<Task finishe...> result=None>) at /usr/lib/python3.11/asyncio/base_events.py:180>
loop end

Comment: Whilst this is amazing detective work, as a solution it's voodoo...  don't litter your codebase with looped calls to `asyncio.sleep(0)`
Comment: Wow. So is there, in general, any consistent way to write "yield to a real task which is not mine, if one exists"? Because the general advice I find is the same as OP found, which is telling people to run `sleep(0)` once.
Comment: Yeah, I think I could have cleaned up and explained the second half of my answer better if I had the time. That is what the other answer finishes and does better.
Comment: @Dan Getz See the answer that I added in response to your comment.
Comment: Nice Investigation! I think I should accept the other answer by @PaulCornelius as it is more complete for a third reader but the credit goes to your answer.
Comment: Great analysis!


Note (save) unmatched entries for dataset_a and dataset_b with python pandas

Question: As you guys can see we lose values from both frames since certain keys do not match up. What I am looking for is note the number of unmatched entries for  left_frame and right_frame. I am not sure how to do this.
left_frame
   key left_value
0    0          a
1    1          b
2    2          c
3    3          d
4    4          e

right_frame
   key right_value
0    2           f
1    3           g
2    4           h
3    5           i
4    6           j

pd.merge(left_frame, right_frame, on='key', how='inner')

** Desired Output: 1**
    key  left_value right_value
0   2    c           f
1   3    d           g
2   4    e           h

** Desired Output: 2**
   key left_value right_value      _merge
0    0          a         NaN   left_only
1    1          b         NaN   left_only
5    5        NaN           i  right_only
6    6        NaN           j  right_only

so basically, I want to have two DataFrames, one for "inner" and other for non-matching
Answer: If you change the type of merge to 'outer' and pass indicator=True then you can see where the non-matching rows come from:
In [193]:
pd.merge(left, right, how='outer', indicator=True)

Out[193]:
   key left_value right_value      _merge
0    0          a         NaN   left_only
1    1          b         NaN   left_only
2    2          c           f        both
3    3          d           g        both
4    4          e           h        both
5    5        NaN           i  right_only
6    6        NaN           j  right_only

You can groupby on this column and call count:
In [194]:
pd.merge(left, right, how='outer', indicator=True).groupby('_merge').count()

Out[194]:
            key  left_value  right_value
_merge
left_only     2           2            0
right_only    2           0            2
both          3           3            3

If you want to filter and save the results:
In [198]:
merged = pd.merge(left, right, how='outer', indicator=True)
merged

Out[198]:
   key left_value right_value      _merge
0    0          a         NaN   left_only
1    1          b         NaN   left_only
2    2          c           f        both
3    3          d           g        both
4    4          e           h        both
5    5        NaN           i  right_only
6    6        NaN           j  right_only

In [199]:
both = merged[merged['_merge'] == 'both']
both

Out[199]:
   key left_value right_value _merge
2    2          c           f   both
3    3          d           g   both
4    4          e           h   both

In [200]:
other = merged[merged['_merge'] != 'both']
other

Out[200]:
   key left_value right_value      _merge
0    0          a         NaN   left_only
1    1          b         NaN   left_only
5    5        NaN           i  right_only
6    6        NaN           j  right_only

Comment: Yes, but I want to store them , after I use drop method for non-matching.
Comment: You can filter my output : `both = merged[merged['_merge'] == 'both']` and `others = merged[merged['_merge'] != 'both']`
Comment: thats sounds like it will work. I will try that. Thank you!


drupal 7 webform add classes to submit button

Question: I am trying to add classes to my webform. In
hook_webform_element
I can do this
if ($element['#type'] == 'checkboxes') {
  $wrapper_classes = array(
    'form-item',
    'webform-component',
    'large-16 medium-8 small-24 columns',
    'webform-component-' . $type,
  );
}
else {
     $wrapper_classes = array(
    'form-item',
    'webform-component',
    'large-8 medium-8 small-24 columns',
    'webform-component-' . $type,
  );
}

But I do not seem to have access to the submit button. I need to add a couple of classes and also only do it on a certain form so suppose I need the $form_id.
Comment: did you try `hook_form_alter` from the Drupal Form API? Let me put this another way. Yes, a webform is made up of webform elements (because years ago they made their own form creation and storage mechanisms separate from Drupal) ... but it's still just a Form and they leverage the Drupal form api still for validation and processing etc. So a custom select widget would be a webform component, the submit button is just a plain HTML input submit.
Answer: You can do this hook_form_alter(). As all the form element are available in hook_form_alter.
function mymodule_form_alter(&$form, &$form_state, $form_id){
    if ($form_id == 'webform_client_form_YOUR_NODE_ID') {
        $form['actions']['submit']['#attributes']['class'][] = 'newclass';
    }
}