webForumDet fria alternativet

Lägga till/ta bort värde ur array

.NET

13 svar · 869 visningar · startad av Travoni

Medlem sedan okt. 20041 556 inlägg
Frågan#1

Låt säga att jag har en array som ser ut så här:

Dim str As String() = "a,b,c,d".split(",")

Om jag nu vill ta bort ex. "b" ur arrayen hur gör jag då?

Medlem sedan aug. 20003 575 inlägg
#2

Istället för .Split, .Replace("b", string.Empty);

Medlem sedan okt. 20041 556 inlägg
#3

Då blir det ett komma över...

.Replace("b", string.Empty).Replace(",,",",")

Kanske... Känns som en fullösning men det kanske funkar.

Medlem sedan okt. 20041 556 inlägg
#4

Vad tror du om något sådant hära:

private bool isInArray(string searchFor, string CommaString) 
{ 
    string[] tmpStr = CommaString.Split(","); 
    for (int i = 0; i <= tmpStr.Length - 1; i++) { 
        if (searchFor == tmpStr(i)) 
            return true; 
    } 
    return false; 
} 

private string removeFromString(string searchFor, string CommaString) 
{ 
    return CommaString.Replace(searchFor, string.Empty).Replace(",,", ","); 
} 

private string addToString(string strToAdd, string CommaString) 
{ 
    if (!isInArray(strToAdd, CommaString)) { 
        return string.Concat(CommaString, ",", strToAdd); 
    } 
    else { 
        return CommaString; 
    } 
}
Medlem sedan juni 20008 205 inlägg
#5

Ändra inte i källsträngen, det är katastrofalt fult. Finns många sätt att göra det på.

List.Remove:

List<string> strings = new List<string>("a,b,c,d".Split(","));
strings.Remove(s => s == "b");

Extension på IEnumerable:

public static IEnumerable<T> AllExcept<T>(this IEnumerable<T> self, T except)
{
    foreach (T value in self) if (value != except) yield return value;
}
...
IEnumerable<string> values = "a,b,c,d".Split(",").AllExcept("b");

Eller med Linq-extensions (otestad):

"a,b,c,d".Split(",").Select(s => s != "b");
Medlem sedan okt. 20041 556 inlägg
#6

Ändra inte i källsträngen, det är katastrofalt fult.

Det låter bra, men hur menar du?

Medlem sedan aug. 20003 575 inlägg
#7

Nickemannen skrev:

Istället för .Split, .Replace("b", string.Empty);

.Replace("b,", string.Empty)

Medlem sedan nov. 20014 054 inlägg
#8

Nickemannen skrev:

.Replace("b,", string.Empty)

Den där är ju inge kul om du skall ta bort sista elementet, där saknar vi en slut ",". Spangos exempel känns mer rätt.

Medlem sedan aug. 20003 575 inlägg
#9

Regex regex = new Regex(@"b\,?");

regex.Replace("a, b, c, b", string.Empty);

Medlem sedan juni 20008 205 inlägg
#10

Travoni skrev:

Det låter bra, men hur menar du?

Det är vansinne att ändra på ett serialiserat värde. Koden blir lättare att läsa, skriva, ändra och felsöka (vilket redan bevisats av den här tråden, med alla ändringar som gjorts på replacevarianterna) om man gör filtreringen på det deserialiserade värdet (dvs arrayen) än om man gör ändringarna på den serialiserade representationen (dvs den kommaseparerade strängen). Ändrar du på hur arrayen representeras som en sträng behöver du bara ändra på två ställen (serialisering/deserialisering) istället för på tre (de förra två + filtreringsfunktionen). Inte osannolikt blir det snabbare också, även om det bara är ett andrahandsargument emot. (Det effektivaste torde vara att göra filtrering och de/serialisering samtidigt, men det känns lite overkill här.)

Medlem sedan okt. 20041 556 inlägg
#11

Ok, jag hajjar.

Jag kan beskriva mitt "problem" ifrån början.

Jag har en xml-fil där jag lagrar värden på detta sätt

<department name="News">
    <item name="canRead" value="Admin,Users,Moderators" />
    <item name="canWrite" value="Admin,Moderators" />
</department>

Nu vill jag lista det rättigheter som ex. Admin har i en checkboxlist varpå en checkbox skall vara ikryssad ifall Admin har rättigheter på respektive post.

När jag uppdaterar så skall värdet returneras med den nya kommaseparerade listan.

Det kan hända att detta är ett dumt system men annars så blir det så många poster i xml-filen. Plus att det blir "fel" när man ex tar bort roller.

<department name="News">
    <item name="AdminCanRead" value="True" />
    <item name="AdminCanWrite" value="True" />
    <item name="UsersCanRead" value="True" />
    <item name="UsersCanWrite" value="False" />
    <item name="ModeratorsCanRead" value="True" />
    <item name="ModeratorsCanWrite" value="True" />
</department>

Alt:

<group name="Admin">
    <item name="CanReadNews" value="True" />
    <item name="CanWriteNews" value="True" />
</group>
<group name="Moderators">
    <item name="CanReadNews" value="True" />
    <item name="CanWriteNews" value="True" />
</group>
<group name="Users">
    <item name="CanReadNews" value="True" />
    <item name="CanWriteNews" value="False" />
</group>

Tips emottages gärna hur jag skall lösa detta.

Medlem sedan juni 20008 205 inlägg
#12

Tja, det är pest eller kolera egentligen när man vill hantera såna här strukturer med XML, men jag skulle använda en enum med FlagsAttribute så att man kan kombinera värden:

[Flags]
enum Permission { None = 0, Read = 1, Write = 2 }

Sen kan du ha en XML-struktur som:

<department name="News">
    <permission for="Admin" allows="Read,Write" />
    <permission for="Moderators" allows="Read,Write" />
    <permission for="Users" allows="Read" />
</department>

Därefter kan du använda Enum.Parse för att göra om det till enum-värden, och kolla med bitmaskoperationer:

Permission p = (Permission)Enum.Parse(typeof(Permission), "Read,Write");
Console.WriteLine("Permission: {0}", p.ToString());
if ((p & Permission.Read) == Permission.Read) Console.WriteLine("Can read");
if ((p & Permission.Write) == Permission.Write) Console.WriteLine("Can write");

Console.WriteLine("Disabling write permission...");
p &= ~Permission.Write; // stäng av write
Console.WriteLine("Permission: {0}", p.ToString());
if ((p & Permission.Read) == Permission.Read) Console.WriteLine("Can read");
if ((p & Permission.Write) == Permission.Write) Console.WriteLine("Can write");

Console.WriteLine("Enabling write permission...");
p |= Permission.Write; // slå på write
Console.WriteLine("Permission: {0}", p.ToString());
if ((p & Permission.Read) == Permission.Read) Console.WriteLine("Can read");
if ((p & Permission.Write) == Permission.Write) Console.WriteLine("Can write");

Det kan se lite mysko ut men är väldigt behändigt och effektivt och hyggligt typsäkert. Minnesregler (p är en variabel med kombinationer av flaggor, x är en flagga):

  • Om (p & x) == x är x satt
  • Om (p & x) == 0 är x inte satt (i exemplet ovan motsvaras 0 av Permission.None)
  • För att stänga av en flagga, använd p &= ~x
  • För att slå på en flagga, använd p |= x

Har noll koll på hur bitvisa operationer ser ut i VB.Net är jag dock rädd :)

Har du sen en klass för en grupps rättigheter på en avdelning skulle den alltså kunna se ut som:

public class DepartmentPermission
{
    public Group Group { get; set; }
    public Department Department { get; set; }
    public Permission Permissions { get; set; }
    public bool CanRead 
    { 
        get { return GetPermission(Permission.Read); } 
        set { SetPermission(Permission.Read, value); }
    }
    public bool CanWrite
    { 
        get { return GetPermission(Permission.Write); } 
        set { SetPermission(Permission.Write, value); }
    }

    private bool GetPermission(Permission p) { return (Permissions & p) == p; }
    private void SetPermission(Permission p, bool on)
    {
        if (on) Permissions |= p;
        else Permissions &= ~p;
    }
}
Medlem sedan okt. 20041 556 inlägg
#13

Tack för att du tar dig tid Spango! :)
Det är kanske en databas jag skall använda ändå.
Det är lite ju lite lättare att hantera, eller vad tror du?

Medlem sedan juni 20008 205 inlägg
#14

Travoni skrev:

Tack för att du tar dig tid Spango! :)
Det är kanske en databas jag skall använda ändå.
Det är lite ju lite lättare att hantera, eller vad tror du?

Tja, det vore kanske enklare om du redan har en databas :) XML är ju sådär när det gäller att representera många-till-många-relationer.

270 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
129 ms — deklarationer (db)
0 ms — hämta statistik (cache)
133 ms — hämta tråd, inlägg och bilagor (db)
134 ms — ändringar (db)