String Array ohne Anführungszeichen ausgeben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
BrickBardo
User
Beiträge: 10
Registriert: Dienstag 8. September 2020, 10:45

Ich habe ein Numpy-Array mit Datentyp String erstellt, es soll mit + und Leerzeichen gefüllt werden, abhängig vom Wert der Zufallszahl.

Code: Alles auswählen

import numpy as np
fsize = 8
def Spielfeld(fsize):
  old_gen = np.empty([fsize,fsize],dtype=str)
  for i in range(0,fsize):
    for j in range(0,fsize):
      zufall = np.random.randint(1,101,dtype=np.int)
      if zufall < 50:
        old_gen[i,j] = '+'
      else:
        old_gen[i,j] = ' '
  return old_gen
old_gen = Spielfeld(fsize)
print(old_gen)
Die Ausgabe sieht wie folgt aus:

[['+' '+' ' ' ' ' ' ' '+' '+' ' ']
['+' '+' '+' '+' '+' '+' '+' '+']
['+' '+' ' ' ' ' ' ' '+' '+' ' ']
['+' '+' '+' '+' ' ' ' ' ' ' ' ']
[' ' ' ' '+' '+' ' ' '+' ' ' '+']
[' ' '+' '+' '+' '+' '+' '+' ' ']
[' ' '+' '+' ' ' ' ' '+' '+' '+']
[' ' ' ' ' ' ' ' '+' '+' ' ' ' ']]

Allerdings möchte ich, dass die Zeichen ohne die Anführungszeichen ausgegeben werden. Wie kann ich dies bewerkstelligen?
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Das ist ja quasi eine verschachtelte Liste. Du iterierst old_gen und gibst jedes Element mit "".join() aus.
Benutzeravatar
__blackjack__
User
Beiträge: 13999
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@BrickBardo: Da fehlen Leerzeilen um das lesbarer zu gestalten.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

Eingerückt wird mit vier Leerzeichen pro Ebene.

Namen sollten keine kryptischen abkürzungen Enthalten. Wenn man `field_size` meint, sollte man nicht `fsize` schreiben. Was `old_gen` bedeuten soll ist mir ein Rätsel. In einer Funktion die ein Spielfeld erzeugt ist an dem Ergebnis dort doch nichts ”altes”‽ Das ist dort ein nigelnagelneues Spielfeld.

Funktionsnamen wie oben schon erwähnt klein geschrieben, damit man `Spielfeld` nicht für eine Klasse hält, und dann ist der Name inhaltlich ein Problem, denn man kann den nicht von einem offensichtlichen Namen für ein Spielfeld unterscheiden. Die Funktion heisst so, wie man ihren Rückgabewert nennen würde. Was man nicht mehr kann, weil ja die Funktion schon so heisst. Funktionen und Methoden werden deshalb üblicherweise nach der Tätigkeit benannt die sie durchführen. Man kann Funktionen dadurch besser von eher passiven Werten unterscheiden und ``spielfeld = erzeuge_spielfeld(42)`` ist dann kein Problem mehr.

Numpy wird hier missbraucht. Erst einmal generell, denn ich sehe in dem gezeigten Quelltext überhaupt keinen Vorteil daran das nicht einfach mit Listen zu machen. Und auch wenn man Numpy unbedingt benutzen will, dann nicht *so*. Erster Gedanken bei Numpy und Schleifen in Python sollte immer sein „ich machen wahrscheinlich etwas falsch“, denn Numpy verwendet man ja gerade um sich langsame Schleifen in Python zu sparen und die in C (und teilweise Fortran) geschriebenen Schleifen zu verwenden die sich hinter den Numpy-Operationen verstecken. Die Funktion wird mit Numpy letztlich zu einem simplen Einzeiler.

Die `numpy.random.randint()`-Funktion sollte nicht mehr verwendet werden.

Code: Alles auswählen

#!/usr/bin/env python3
import numpy as np

FIELD_SIZE = 8


def erzeuge_spielfeld(size):
    return np.random.default_rng().choice(["+", " "], (size, size))


def main():
    spielfeld = erzeuge_spielfeld(FIELD_SIZE)
    print(spielfeld)
    print("\n".join("".join(row) for row in spielfeld))


if __name__ == "__main__":
    main()
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Benutzeravatar
ThomasL
User
Beiträge: 1378
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Hi,
wie immer ist mir Blacky zuvor gekommen.
Ich poste trotzdem mal meine Lösungen,
einmal ohne Numpy weil nicht notwendig

Code: Alles auswählen

import random

def create_grid(size):
    new_grid = [''.join(random.choice(['+', ' ']) for x in range(size)) for y in range(size)]
    return new_grid

grid = create_grid(8)

for row in grid:
    print(row)
und einmal mit Numpy, sieht so ähnlich aus wie bei Blacky.

Code: Alles auswählen

grid = np.random.choice([32, 43], size=(8, 8), replace=True, p=(0.5, 0.5))

for row in grid:
    for value in row:
        print(chr(value), end='')
    print()
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
BrickBardo
User
Beiträge: 10
Registriert: Dienstag 8. September 2020, 10:45

Danke schon mal für eure Antworten und die Mühe, die ihr euch gemacht habt. Aber so richtig hilft mir das leider nicht weiter. Weil ich möchte es ja so machen, wie ich es oben geschrieben habe. Die Antwort könnte natürlich auch sein, dass Python das so gar nicht darstellen kann (BTW: Java kann es). Es mag auch sein, dass dies eine furchtbar ineffiziente Methode ist, aber das ist im Moment nicht mein Fokus.
Benutzeravatar
__blackjack__
User
Beiträge: 13999
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@BrickBardo: Was genau hilft Die dabei nicht weiter? Beide Antworten zeigen wie man das in Python schreiben würde, einmal mit Numpy, einmal ohne, und beide Antworten zeigen wie man die Ausgabe ohne die Anführungszeichen macht.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

@BrickBardo: __blackjack__ hat Dir doch die Lösungen gezeigt, wie man ein numpy-Array erzeugt. So programmiert mit Python. In Java mußt Du auch Deine explizite Darstellung programmieren. Ist es wichtig, dass + zu _ im Verhältnis 49:51 erzeugt werden?
Dann mußt Du noch die Wahrscheinlichkeit angeben:

Code: Alles auswählen

def erzeuge_spielfeld(size):
    return np.random.default_rng().choice(["+", " "], (size, size), p=[0.49, 0.51])
Benutzeravatar
noisefloor
User
Beiträge: 4172
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@BrickBardo: im Numpy-Array werden die "" oder '' immer mit angezeigt, weil du einen Array von Arrays hast und der "innere" Array Strings enthält. Die Anführungsstrichen werden dann nicht mit angezeigt, wenn du Strings direkt ausgibts.

Gruß, noisefloor
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Wenn du die Klammern behalten willst, aber nicht die Anführungszeichen musst du dein Spielfeld erst in einen String umwandeln und dann dort die mit replace() zum Beispiel die ' entfernen, dann sähe das Ergebnis so aus:

Code: Alles auswählen

[[+         + +  ]
 [    + +   +    ]
 [+ + +   + + +  ]
 [  +   + +   +  ]
 [+ + + +   +    ]
 [+     +   +    ]
 [    +       +  ]
 [  +   +       +]]

oder mit iterieren über old_gen und dann mit "".join(row) ausgegeben in einem f-String mit zwei Klammern umschlossen so:

Code: Alles auswählen

[++ +++ +]
[    +   ]
[++++  + ]
[ ++  +  ]
[ +++    ]
[  ++ +++]
[     + +]
[   ++  +]
Zeig doch einmal mal wie die Ausagbe später aussehen soll, so wie du es oben Beschreiben hast wurde es jetzt mehrfach gezeigt. Also entweder besser beschreiben oder Beispiele bringen.
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

@Jankie: die Stringrepräsentation eines Numpy-Arrays ist eigentlich nicht für die allgemeine Darstellung gedacht, sondern nur zu Debuggingzwecken. Es ist gar nicht garantiert, dass man per replace immer die gewünschte Form erhält.
Für die Ausgabe wandelt man die Arrays immer explizit um.
BrickBardo
User
Beiträge: 10
Registriert: Dienstag 8. September 2020, 10:45

Ich habe das Problem nun folgenderweise gelöst:

Code: Alles auswählen

import numpy as np
import sys
fsize = 16

def Spielfeld():
  old_gen = np.empty([fsize,fsize],dtype=str)
  for i in range(0,fsize):
    for j in range(0,fsize):
      zufall = np.random.randint(1,101,dtype=int)
      if zufall < 25:
        old_gen[i,j] = '+'
      else:
        old_gen[i,j] = ' '
  return old_gen
  
def Ausgabe(old_gen):
  for i in range(0,fsize):
    for j in range(0,fsize):
      sys.stdout.write(old_gen[i,j] + ' ')
    print()

old_gen = Spielfeld()
old_gen_out = Ausgabe(old_gen)
Noisefloor hatte mich auf den Gedanken gebracht, das die Einzelausgabe eines Strings immer ohne die Anführungszeichen erfolgt. So war das übrigens auch in Java gelöst, weil Java nicht über die Möglichkeit verfügt ein Array direkt über system.out.print() auszugeben. Das hat auch den angenehmen Nebeneffekt, dass die Klammern nicht mehr mitausgegeben werden.
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

@BrickBardo: auch wenn es nervt. Du solltest Dir von Anfang an eine saubere Schreibweise angewöhnen. Wenn Du Dir jetzt die Schlamperei angewöhnst, wirst Du schwer wieder davon wegkommen. Eingerückt wird immer mit 4 Leerzeichen pro Eben eingerückt. Variablennamen und Funktionsnamen werden komplett klein geschrieben. Funktionen sind nach Tätigkeiten benannt. Benutze keine Abkürzungen, oder soll old_gen tatsächlich ein altes Gen beschreiben (müßte dann old_gene heißen)? Konstanten werden komplett gross geschrieben: FSIZE, wobei hier auch wieder ausgeschrieben werden sollte: FIELD_SIZE

Im Moment programmierst Du irgend ein BASIC in Python-Syntax (nicht mal in Java würde man so programmieren). Du nutzt kein numpy. Wenn Dir die numpy-Methoden noch zu kompliziert sind, dann bleibe bei den Python-Grunddatentypen.
Man iteriert nicht über den Index um dann auf Elemente mit eckigen Klammern zuzugreifen, sondern man iteriert über die Objekte direkt.
Wenn man nicht ganz so kompakt schreiben will wie __blackjack__, ThomasL hat die Ausgabe so geschrieben, wie sie sein sollte.
`Spielfeld` sollte die Feldgröße als Argument bekommen und `Ausgabe` sollte gar nicht explizit die Feldgröße benutzen, sondern aus dem Gen-Feld ermitteln.
`Ausgabe` hat keinen Rückgabewert, diesen None-Wert an old_gen_out zu binden ist daher unsinnig.
Antworten