[Question]
  [
To neutralize data, recursively replace all numbers (not digits!) with zeros and all characters (not strings!) with spaces.
You must accept any single number, character, or string, or possibly recursive array\* of mixed numeric/character data that your language can handle. For example, you must accept actual strings (and not restrict your input to lists of single characters) if your language can handle such.
If your language contains a built-in which does all or most of this task, I would appreciate an additional alternative version without it.
The shortest submission in each language is a winner, and will receive an upvote from me.
**Sample cases**
1. `""` → `""`
2. `7` → `0`
3. `123.456` → `0`
4. `"X"` → `" "`
5. `" "` → `" "`
6. `"Yo!"` → `" "`
7. `[]` → `[]`
8. `[-1.2E3]` → `[0]`
9. `["Hey"]` → `[" "]`
10. `["H","e","y"]` → `[" "," "," "]`
11. `["R",2,"D",2]` → `[" ",0," ",0]`
12. `["C","3","P",0]` → `[" "," "," ",0]`
13. `["THX",[1138]]` → `[" ",[0]]`
14. `["T","H","X",[1138]]` → `[" "," "," ",[0]]`
15. `[[["H"],"e",1,1,0],[[-3],"arth"]]` → `[[[" "]," ",0,0,0],[[0]," "]]`
\* If your language has several types which can equally well represent arrays like the above examples, you may chose to support only one. Two entries can both win, even though they are using the same language, by each going with a different data type.
  
[Answer]
## JavaScript (ES6), ~~53~~ 47 bytes
```
f=o=>o.big?o.replace(/./g,' '):o.map?o.map(f):0
```
### Test cases
```
f=o=>o.big?o.replace(/./g,' '):o.map?o.map(f):0
test = [
  "",
  7,
  123.456,
  "X",
  "  ",
  "Yo!",
  [],
  [-1.2E3],
  ["Hey"],
  ["H","e","y"],
  ["R",2,"D",2],
  ["C","3","P",0],
  ["THX",[1138]],
  ["T","H","X",[1138]],
  [[["H"],"e",1,1,0],[[-3],"arth"]]
];
test.map(o => {
  console.log(JSON.stringify(o), '=>', JSON.stringify(f(o)));
});
```
[Answer]
# [Python 2](https://docs.python.org/2/), 52 bytes
```
f=lambda x:1-(x<{})and map(f,x)if x<''else' '*len(x)
```
[Try it online!](https://tio.run/nexus/python2#@59mm5OYm5SSqFBhZairUWFTXauZmJeikJtYoJGmU6GZmaZQYaOunppTnKquoK6Vk5qnUaH5v6AoM69EIU0jOjpa3UM9VkdBPVVdR8EQjAyA3OhoXWOQaGJRSYZ6bKzmfwA "Python 2 – TIO Nexus")
### How it works
Python lets you compare different types. Numeric types are always smaller than iterables, and iterables are sorted by their type names, so
```
0 < {} < [] < '' < ()
```
This way, **f** does the following.
* If **x** is numeric `x<{}` returns *True* and `1-(x<{})` returns **0**. The code after `and` does not get executed.
* If **x** is iterable, `1-(x<{})` returns **1** (truthy), so the code after `and` gets executed.
	+ If **x** is a list, `x<''` is true and **f** gets mapped over its items.
	+ If **x** is a string, `x<''` is false and **x** is replaced with a string of spaces of the same length.
[Answer]
## Ruby, ~~54 53~~ 49 bytes
```
f=->a{a*0==0?0:a*0==[]?a.map{|x|f[x]}:" "*a.size}
```
Maybe there is a better way, but:
* x\*0 == 0 for integers
* x\*0 == "" for strings
* x\*0 == [] for arrays
[Answer]
## Mathematica, 51 bytes
I've currently got two solutions at this byte count:
```
#/._?NumberQ->0/.x_String:>StringReplace[x,_->" "]&
StringReplace[#,_->" "]~Check~#&//@#/._?NumberQ->0&
```
The second one throws a bunch of warnings which can be ignored.
### Explanation
In either case, we start by turning numbers into zeros with
```
#/._?NumberQ->0
```
Then to process the string, there are two options. Either, we use another substitution that only applies to strings:
```
.../.x_String:>StringReplace[x,_->" "]
```
Or, we use the `MapAll` operator `//@` which maps a function over every single element in a nested list. The catch here is that we'll be trying to use `StringReplace` on zeros as well as the symbol `List` (since `//@` also goes through the heads of expressions), so we need to use `Check` (sort of like a `catch` statement in other languages) to avoid wreaking havoc with those values:
```
StringReplace[#,_->" "]~Check~#&//@...
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 4 bytes
```
nOa⁶
```
This is a monadic link. Jelly's implicit printing does a lot of splatting; to verify that the output is what it should be, you can view the internal representation with `ŒṘ`. Note that this exposes strings as lists of characters, which is how the Jelly interpreter implements them.
[Try it online!](https://tio.run/nexus/jelly#@5/nn/iocdt/ncPtRyc93DnjUdOaSIWHO7Y/apgTUJSZV1KsUJKRqgBkpBblJeYoFKUWFKUWp@aVJJZk5ucp5KdBpQtKSxQS81LAvPzSEiBX7///6OhoJQ@lWB0FpVQlHQVDMDIAcqOjdY1BoolFJRlKsbEA "Jelly – TIO Nexus")
### How it works
```
nOa⁶  Monadic link. Argument: z
 O    Ordinal; replace all characters with the code points.
      This does not affect numbers.
n     Vectorizing not-equal; compare z with the result to the right, replacing
      characters with 1 and numbers with 0.
  a⁶  Logical AND space; replace all 1's with spaces.
```
[Answer]
# Perl 6, ~~34~~ 48 bytes
```
{.deepmap:{$_~~Str??" "x.comb!!0}}
```
```
{$_~~List??$_».&?BLOCK!!$_~~Str??" "x .comb!!0}
```
Expanded:
```
{                          # block-based lambda
    $_ ~~ List             # if argument is a list/array
        ?? $_».&?BLOCK     # then recurse for each element (&?BLOCK is a compile-time var)
        !! $_ ~~ Str       # else if argument is a string
            ?? " "x .comb  # then use space repeated by the string's length,
            !! 0           # else use the number 0
}
```
[Answer]
## [GAP](http://gap-system.org), 91 bytes
GAP has a method `Zero` that returns the neutral additive element corresponding to an element of an additive structure. That handles numbers and even lists of numbers which are considered vectors, but not arbitrary lists. So let's add these and Chars and use that Strings are lists of Chars:
```
InstallOtherMethod(Zero,[IsChar],c->' ');
InstallOtherMethod(Zero,[IsList],l->List(l,Zero));
```
(I'm not counting the newline as it isn't needed.) Of course this is far away from the intended use of `Zero`, and GAP would complain if I hadn't used `Install`*Other*`Method`. Now I can do:
```
gap> Zero([[["H"],"e",1,1,0],[[-3],"arth"]]);
[ [ [ " " ], " ", 0, 0, 0 ], [ [ 0 ], "    " ] ]
```
I wouldn't say that the builtin does most of the job, one might rather suspect that writing a normal function should be shorter, but my best try doing that was 92 bytes long:
```
f:=function(x)if IsInt(x)then return 0;elif IsList(x)then return List(x,f);fi;return' ';end;
```
[Answer]
## Haskell, 115 bytes
My language cannot handle any mix of numbers and strings in lists (but of course you can define a sum type and put that in a list), and its standard lists cannot handle differently nested lists. So I'm just doing what it can handle. I think that is not unfair because it is still long, and I mainly do it to show features of haskell that are rarely seen in haskell golfing solutions. Note that Strings are lists of Chars.
```
class N a where n::a->a
instance N Double where n _=0
instance N Char where n _=' '
instance N a=>N[a]where n=map n
```
This handles any number as Double:
```
*Main> n 42
0.0
*Main> n 123.456
0.0
*Main> n "hi"
"  "
*Main> n [[1,2],[3,4,5]]
[[0.0,0.0],[0.0,0.0,0.0]]
*Main> n ["hello","world!"]
["     ","      "]
```
[Answer]
# PHP, 91 bytes
```
function f($a){return!is_array($a)?is_string($a)?str_pad("",strlen($a)):0:array_map(f,$a);}
```
if parameter is array: recurse using `array_map`.  
else if parameter is string: generate a strings of spaces with the same length.  
else `0`.
`is_string` saves one byte over `is_numeric`;
negating `is_array()` renders parentheses obsolete.
Altogether it´s 17 bytes shorter than `if()recursion-loop;else x?string:number` with a call by reference.
[Answer]
## Python 2, 59 bytes
```
g=lambda d:0if d*0==0else " "*len(d)if d*0==""else map(g,d)
```
uses G B's way to determine types
[Answer]
##  Common Lisp, 87
```
(defun c(e)(typecase e(list(mapcar'c e))(number 0)(string(map'string(lambda(u)#\ )e))))
```
Ungolfed
```
(defun c(e)
  (typecase e
    (list (mapcar #'c e))
    (number 0)
    (string (map 'string (lambda(u) #\space) e))))
```
Example
```
> (c '((("H") "e" 1 1 0) ((-3) "arth")))
(((" ") " " 0 0 0) ((0) "    "))
```
[Answer]
# [APL (Dyalog)](https://www.dyalog.com/) 13.2 and earlier, 1 byte
Until and including version 13.2, monadic `∊` did exactly this. The old behaviour can be activated by setting `⎕ML` (**M**igration **L**evel) to zero.
```
∊
```
[Try it online!](https://tio.run/nexus/apl-dyalog-classic#e9Q31dfnUdsEg/9pQPJRR9d/t6L8XK9gfz8g19zQ1PJRzzaukHy4gJkBUOA/REAhTQGmWEFdSUmdC4uwOVZRQyNjPRNTM6xyShHYTVJSUMAhEZmviF0mOha7sK6hnpGrMQ5JJY/USiWccko6SqlAjFtFkJKOkY6SC5DEpcIZqN8YiAOUdAxwqQnxiFDSiTY0NLaIxakEaATIOYQURoNcHQt2tiEQGsTqREfrGgMFEotKMpSAugA "APL (Dyalog Classic) – TIO Nexus")
Without using old behaviour it is 4 bytes:
```
⊃0⍴⊂
```
[Try it online!](https://tio.run/nexus/apl-dyalog#@5/2qG3Co65mg0e9Wx51Nf13K8rP9Qr29wOKmhuaWj7q2cYVkg8XMDMACvyHCCikKcAUK6grKalzYRE2xypqaGSsZ2JqhlVOKQK7SUoKCjgkIvMVsctEx2IX1jXUM3I1xiGp5JFaqYRTTklHKRWIcasIUtIx0lFyAZK4VDgD9RsDcYCSjgEuNSEeEUo60YaGxhaxOJUAjQA5h5DCaJCrY8HONgRCg1id6GhdY6BAYlFJhhJQFwA "APL (Dyalog Unicode) – TIO Nexus")
`⊂` enclose
`0⍴` make a length-zero list of copies of the entire input (preserves only structure and type info)
`⊃` coerce one element from that (creates a prototypical array)
[Answer]
## Groovy, 53 bytes
```
{[it].collectNested{it in String?" "*it.size():0}[0]}
```
This is an unnamed closure.
[Try it here!](http://ideone.com/dxHel6)
**Explanation**:
Groovy has this method [`.collectNested`](http://docs.groovy-lang.org/latest/html/groovy-jdk/java/util/Collection.html#collectNested(groovy.lang.Closure)) which helps to iterate through a list as if it was flattened.
To handle special cases where only an integer or a string is passed without a list, simply wrap every input into a list and output the first element.
[Answer]
## Pyke, 8 bytes [(Old version)](https://github.com/muddyfish/PYKE/commit/add0053688a23382f727a646f56fe657f61af8c2)
```
.FZ*0+d&
```
Explanation:
```
.FZ*0+d& - for i in deep_for(input):
  Z*     -    i*0
    0+   -   ^ + 0
      d& -  ^ and " "
```
This no longer works as an update made it so falsies of other types where there are truthies automatically convert to the falsey of the truthy type.
[Answer]
## C#, ~~197~~ 195 Bytes
```
a=>{if(a is string||a is char)return new string(' ',(a as string)?.Length??1);try{System.Convert.ToDecimal(a);return 0;}catch{}var b=(object[])a;for(int i=0;i<b.Length;)b[i]=n(b[i++]);return b;};
```
This function handles `char`, `string`, any builtin number type and recursive arrays.
Full program, ungolfed whit output helper:
```
using System.Linq;    
class Class
{
    public static void Main()
    {
        System.Func<object, object> n = null;
        n = a => 
        {
            if (a is string || a is char)
                return new string(' ', (a as string)?.Length ?? 1);
            try
            {
                System.Convert.ToDecimal(a);
                return 0;
            }
            catch { }
            var b = (object[])a;
            for (int i = 0; i < b.Length;)
                b[i] = n(b[i++]);
            return b;
        };
        var result = n(new object[] { new object[] { new object[] { "H" }, 'e', 1.5, 1, 0 }, new object[] { new object[] { -3 }, "arth" } });
        System.Console.WriteLine(Output(result));
        System.Console.Read();
    }
    static string Output(object x)
    {
        var arr = x as object[];
        if (arr != null)
            return "[" + string.Join(",", arr.Select(Output)) + "]";
        else
            return x.ToString();
    }
};
```
The `using` statement is only needed for the output helper, not for the actual function.
[Try Online](http://csharppad.com/gist/5feca8f2e9f5f46525e4d561c76393fa)
[Answer]
# Javascript ES6, 81 chars
```
f=(x,t)=>(t=g=>eval(`try{x.${g}}catch(e){}`))`replace(/./g,' ')`||t`map(f)`||x&&0
```
Test:
```
f=(x,t)=>(t=g=>eval(`try{x.${g}}catch(e){}`))`replace(/./g,' ')`||t`map(f)`||x&&0
console.log(
`"" → ""
7 → 0
123.456 → 0
"X" → " "
"  " → "  "
"Yo!" → "   "
[] → []
[-1.2E3] → [0]
["Hey"] → ["   "]
["H","e","y"] → [" "," "," "]
["R",2,"D",2] → [" ",0," ",0]
["C","3","P",0] → [" "," "," ",0]
["THX",[1138]] → ["   ",[0]]
["T","H","X",[1138]] → [" "," "," ",[0]]
[[["H"],"e",1,1,0],[[-3],"arth"]] → [[[" "]," ",0,0,0],[[0],"    "]]`
.split`
`.map(s => s.split` → `.map(eval))
.every(([s,k]) => JSON.stringify(f(s))==JSON.stringify(k)))
```
[Answer]
# Java 7, 262 (268) bytes
```
import java.util.*;Object c(Object o){if(o instanceof List){List r=new ArrayList();for(Object x:(List)o)r.add(c(x));return r;}if(o instanceof String){String r="\"";for(int i=((String)o).length();i-->0;r+=" ");return r+"\"";}return o instanceof Number?0:o instanceof Character?"' '":"";}
```
282 + 6 for the added `\"` and `'` to pretty-print the String and characters.
**Explanation:**
```
import java.util.*;            // Required import for List and ArrayList
Object c(Object o){            // Method with Object parameter and Object return-type
  if(o instanceof List){       //  If the input is a List
    List r=new ArrayList();    //   Create a result-list
    for(Object x:(List)o)      //   Loop over the items of the input-list
      r.add(c(x));             //    And add all items with a recursive-call to this method
                               //   End of loop (implicit / single-line body)
    return r;                  //   Return result-list
  }if(o instanceof String){    //  If the input is a String instead
    String r="\"";             //   Create a result-String (starting with `"`
    for(int i=((String)o).length();i-->0;r+=" ");
                               //   Replace all characters in the String with a space
    return r+"\"";             //   Return the result within double-quotes
  }
  return o instanceof Number?  //  If the input is an integer or decimal instead:
    0                          //   Return 0
   :o instanceof Character?    //  If the input is a character instead:
    "' '"                      //   Return ' '
   :                           //  Else:
    "";                        //   Return an empty String
}                              // End of method
```
**Test code:**
[Try it here.](https://tio.run/nexus/java-openjdk#tVHLT8IwGL/zV3z20lXCwpivsKAxeuDgIxEOGPVQRoGS0ZKuQ8myvx27MSQjusASL22//h7fi88XUmmY0SW1I80D@9Sr@QENQ3ikXMQ1gFBTzX1YPw9nzNfgW/lDkpiPLQlcGIbwmRzDAw81idMTVEewT7hViq7S2CLeWKqt9KttZVRJlE1HI8u3vgjxFNOREqC8ZN@3pxUXExJvbuON3hHKDLnQwDuWlTMksQMmJnpq8vFG47rpqXoHAdqZ1zNpkoeFLE/RfMjUTbNd@L2bUkV9bQCEAaN2ql4DLKJhYKaSD2cp@QjmZmB5IW8fQEk6PIDeKtRsbstI2wsD6UCYdhEy/f4NX5aiTsu1z84vSjl4gEtxBFBeAnqVJ@WMvf0ew43jdOsNx24xl3hJcrwWddkKVZPiLiZe9mDbxwpXtHrJHVq50f0urtRVvztAG4dfccdxrzLnatX2t/3@TGCA/y3b4Z9ZOWmawlKcwtXcMQ43brg7FaJKT1GxnaSWrL8B)
```
import java.util.*;
class M{
  static Object c(Object o){if(o instanceof List){List r=new ArrayList();for(Object x:(List)o)r.add(c(x));return r;}if(o instanceof String){String r="\"";for(int i=((String)o).length();i-->0;r+=" ");return r+"\"";}return o instanceof Number?0:o instanceof Character?"' '":"";}
  
  public static void main(String[] a){
    System.out.println(c(""));
    System.out.println(c(7));
    System.out.println(c(123.456));
    System.out.println(c('X'));
    System.out.println(c("  "));
    System.out.println(c("Yo!"));
    System.out.println(c(new ArrayList()));
    System.out.println(c(new ArrayList(){{add(-1.2e3);}}));
    System.out.println(c(new ArrayList(){{add("Hey");}}));
    System.out.println(c(new ArrayList(){{add('H');add('e');add('y');}}));
    System.out.println(c(new ArrayList(){{add('R');add(2);add('D');add(2);}}));
    System.out.println(c(new ArrayList(){{add("THX");add(new ArrayList(){{add(1138);}});}}));
    System.out.println(c(new ArrayList(){{add('T');add('H');add('X');add(new ArrayList(){{add(1138);}});}}));
    System.out.println(c(new ArrayList(){{add(new ArrayList(){{add(new ArrayList(){{add('H');}});add('e');add(1);add(1);add(0);}});add(new ArrayList(){{add(new ArrayList(){{add(-3);}});add("arth");}});}}));
  }
}
```
**Output:**
```
""
0
0
' '
"  "
"   "
[]
[0]
["   "]
[' ', ' ', ' ']
[' ', 0, ' ', 0]
["   ", [0]]
[' ', ' ', ' ', [0]]
[[[' '], ' ', 0, 0, 0], [[0], "    "]]
```
]