Anonymous collection initializer for a dictionary - c#

Is it possible to implicitly declare next Dictionary<HyperLink, Anonymous>:
{ urlA, new { Text = "TextA", Url = "UrlA" } },
{ urlB, new { Text = "TextB", Url = "UrlB" } }
so I could use it this way:
foreach (var k in dic)
{
k.Key.Text = k.Value.Text;
k.Key.NavigateUrl = k.Value.Url;
}
?

How about:
var dict = new[] {
new { Text = "TextA", Url = "UrlA" },
new { Text = "TextB", Url = "UrlB" }
}.ToDictionary(x => x.Url);
// or to add separately:
dict.Add("UrlC", new { Text = "TextC", Url = "UrlC" });
However, you could just foreach on a list/array...
var arr = new[] {
new { Text = "TextA", Url = "UrlA" },
new { Text = "TextB", Url = "UrlB" }
};
foreach (var item in arr) {
Console.WriteLine("{0}: {1}", item.Text, item.Url);
}
You only need a dictionary if you need O(1) lookup via the (unique) key.

Yes, but only with great workaround, and only within a method.
This is how you can do it:
static Dictionary<TKey, TValue> NewDictionary<TKey, TValue>(TKey key, TValue value)
{
return new Dictionary<TKey, TValue>();
}
public void DictRun()
{
var myDict = NewDictionary(new { url="a"},
new { Text = "dollar", Url ="urlA"});
myDict.Add(new { url = "b" }, new { Text = "pound", Url = "urlB" });
myDict.Add(new { url = "c" }, new { Text = "rm", Url = "urlc" });
foreach (var k in myDict)
{
var url= k.Key.url;
var txt= k.Value.Text;
Console.WriteLine(url);
Console.WriteLine(txt);
}
}
You can refer to this SO question for more info.

Related

My C# WPF webscraper returns error when more than one result is found

I am working on a WPF XAML application that scrapes certain websites for products. I have the search part working and it finds what I'm looking for. But as soon as there is more then 1 result I get a System.InvalidoperationException. I use a ObservableCollection to put the results into a <ListBox>.
Here is the search method:
private static ObservableCollection<EntryModel> _entries = new ObservableCollection<EntryModel>();
public static ObservableCollection<EntryModel> LoadCollectionData
{
get { return _entries; }
set { _entries = value; }
}
public static void PrehmSearchResults(string SearchQuery)
{
HtmlWeb web = new HtmlWeb();
try
{
string ZoekOpdracht = SearchQuery.Replace(" ", "+");
HtmlDocument doc = web.Load("https://www.prehmshop.de/advanced_search_result.php?keywords=" + ZoekOpdracht);
var title = doc.DocumentNode.CssSelect("div.header_cell > a").Single().InnerText;
var links = doc.DocumentNode.CssSelect("a.product_link");
var productLink = new List<string>();
var productTitle = new List<string>();
foreach (var item in links)
{
if (item.Attributes["href"].Value.Contains(".html"))
{
productLink.Add(item.Attributes["href"].Value);
productTitle.Add(title);
}
}
var TitleAndLink = productLink.Zip(productTitle, (l, t) => new { productLink = l, productTitle = t });
foreach (var nw in TitleAndLink)
{
var product = new List<EntryModel>();
var adDetails = new EntryModel
{
Title = nw.productTitle,
Link = nw.productLink
};
Debug.Print(adDetails.ToString());
var ZoekOpdrachtInTitle = adDetails.Title.ToLower().Contains(ZoekOpdracht.ToLower());
if (ZoekOpdrachtInTitle)
{
_entries.Add(adDetails);
}
}
}
So I found the solution without changing too much code. thanks for the help from #PaulSinnema.
The link is part of the title so I only had to change
var title = doc.DocumentNode.CssSelect("div.header_cell > a").ToList();
And I had to change the foreach loop:
foreach (var item in title)
{
if (item.Attributes["href"].Value.Contains(".html"))
{
productLink.Add(item.Attributes["href"].Value);
productTitle.Add(item.InnerText);
}
}

Assigning values to array elements based on a look up table

HI i am writing a c# program where i need to populate a array based on a look up table and set of string arrays with metadata. My lookup table looks like this (Table with key: transmitter, value: Array of receiver)
{
LED1: ["px1","px2","px3"],
LED2: ["px4","px5","px6"]
}
and my meta arrays looks like this (It is dynamic. Just an example. This comes as a response from DB query.)
var transmitters = new string[] { "LED1", "LED2" };
var receivers = new string[] { "px1", "px2", "px3", "px4", "px5", "px6" };
My requirement is
If the transmitter LED1 or LED2 (or any other transmitter) is present in the lookup table, the value of the transmitter (ie ["px1","px2","px3"]) has to be compared with the receiver which are present in the lookup and led has to be marked yellow.
Orphan tranmitter or/ receiver has to be marked red.
Example
LookUp
{
LED1: ["px1", "px2", "px3"],
LED2: ["px5", "px8"]
}
Tranmitters and receivers
var transmitters = new string[] { "led1", "led2" };
var receivers = new string[] { "px1", "px2", "px3", "px4", "px5", "px6" };
the result should be a list as
led1-yellow
px1-yellow
px2-yellow
px3-yellow
led2-yellow
px5-yellow
px4-red
px6-red.
I have written code that works
public class Program
{
public static void Main()
{
var transmitters = new string[] { "led1", "led2" };
var receivers = new string[] { "px1", "px2", "px3", "px4", "px5", "px6" };
var lookup = new Dictionary<string, string[]>() { { "led1", new string[] { "px1", "px2", "px3" } }, { "led2", new string[] { "px5", "px8" } } };
var blocks = new List<Block>();
var blocksTracker = new List<string>();
foreach (var transmitter in transmitters)
{
if (lookup.ContainsKey(transmitter))
{
var receiverLookup = lookup[transmitter];
var intersection = receivers.Intersect(receiverLookup).ToArray();
if (intersection.Length > 0)
{
blocks.Add(new Block() { Id = transmitter, status = "yellow" });
blocksTracker.Add(transmitter);
foreach (var receiver in intersection)
{
blocks.Add(new Block() { Id = receiver, status = "yellow" });
blocksTracker.Add(receiver);
}
}
else
{
blocks.Add(new Block() { Id = transmitter, status = "red" });
blocksTracker.Add(transmitter);
}
}
}
}
}
I am new to c# and i wanted to know if there is a better way of doing this. Please help. You can see the working fiddle Here

values inside the details are null

I see that there are elements. But its not adding to this object, I see null for Name and bytes...
var req = new Details()
{
Saver= new List<SaverDetails>()
{
new SaverDetails()
}
};
foreach (var t in files.ToList())
{
req.Saver.Add(
new SaverDetails()
{
Name= Path.GetFileName(t),
bytes = File.ReadAllBytes(t)
});
}

foreach and index in .ToDictionary C#

I am web-scraping some data and trying to write the scraped data to a json file using C# newtonsoft.Json
I get stuck when writing a foreach in my .ToDictionary function as well as not being able to ++ an index into my .ToDictionary function.
My class:
public class JsonParametersData
{
public bool required { get; set; }
public bool list { get; set; }
public List<string> options { get; set; }
}
My arrays
var jsonData = new List<Dictionary<string, Dictionary<string, JsonParametersData>>>();
var moduleParameters = new List<string>();
var parameterOptionsArray = new List<List<string>>();
var parameterOptions = new List<string>();
var requiredArray = new List<bool>();
var listArray = new List<bool>();
string moduleName = item.Attributes["href"].Value.Replace("_module.html", "");
The code which is commented shows what I am trying to do.
int index = 0;
jsonData.Add(new Dictionary<string, Dictionary<string, JsonParametersData>>()
{
{
moduleName,
moduleParameters
.ToDictionary(n => n,
n => new JsonParametersData
{
required = requiredArray[index],
list = listArray[index],
options = new List<string>() { "option1", "option2" },
/*
foreach (var parameteroption in parameterOptionsArray[index])
{
options.Add(parameteroption);
}
index++;
*/
})
}
});
string json = JsonConvert.SerializeObject(jsonData.ToArray());
//write string to file
System.IO.File.WriteAllText(#"path", json);
Your parameterOptionsArray is not an Array, but a List of lists.
The thing is that parameterOptionsArray[index] is a List, not a string. So you should use AddRange() instead of Add().
parameterOptionsArray.Foreach(parameteroption => options.AddRange(parameteroption));
As I´ve written in the comments you can make only assignments in an object-initializer. Thus the following is allowed:
var a = new { MyMember = anInstance }
whilst this is not:
var a = new { MyMember = anInstance, anInstance.DoSomething() };
That´s one of those cases where you should not use Linq at all, as it leads to more confusion than it helps. Instead use a good old-styled loop:
int index = 0;
var innerDict = new Dictionary<string, JsonParametersData>();
foreach(var name in moduleParameters)
{
innerDict[name] = new JsonParametersData
{
required = requiredArray[index],
list = listArray[index],
options = new List<string>() { "option1", "option2" },
}
innerDict[name].Options.AddRange(parameterOptionsArray[index]);
index++;
}
var dict = new Dictionary<string, Dictionary<string, JsonParametersData>>();
dict[moduleName] = innerDict;
jsonData.Add(dict);
string json = JsonConvert.SerializeObject(jsonData.ToArray());
You appear to have a jagged array in parameterOptionsArray. You can make use of SelectMany here. Perhaps following sample can help:
string[][] parameterOptionsArray = new string[2][];
parameterOptionsArray[0] = new string[2];
parameterOptionsArray[0][0] = "1";
parameterOptionsArray[0][1] = "2";
parameterOptionsArray[1] = new string[2];
parameterOptionsArray[1][0] = "3";
parameterOptionsArray[1][1] = "4";
var testing = new {options = parameterOptionsArray.SelectMany(x => x).ToList()};
testing.options.ForEach(x => Console.WriteLine(x));

Confused about how get value from DictionaryList at specific index

I am using a DictionaryList to keep some values coming from an xml file
this is the my xml file
<DnsServers>
<Dns>
<Name>Google</Name>
<Value>8.8.8.8,8.8.4.4</Value>
</Dns>
<Dns>
<Name>Telekom</Name>
<Value>195.175.39.39,195.175.39.40</Value>
</Dns>
</DnsServers>
and then populating a combobax just key values like this way .
void ReadFromDnsServerList()
{
_nameValueDictionary = new Dictionary<string, string>();
//var list = new List<string>();
XDocument doc = XDocument.Load("DnsServerList.xml");
if (doc.Root != null)
{
var keyValueXml = from c in doc.Root.Descendants("Dns")
select new
{
name = c.Element("Name").Value,
value = c.Element("Value").Value
};
foreach (var info in keyValueXml)
{
_nameValueDictionary.Add(info.name,info.value);
}
foreach (KeyValuePair<string, string> item in _nameValueDictionary)
{
cmbDns.Items.Add(item.Key);
}
}
}
I am wondering that How can I get corresponding dns value inside cmbDns_SelectedIndexChanged
change event somethinglike this
name=Google value =8.8.8.8,8.8.4.4
Try this:
void ReadFromDnsServerList()
{
_nameValueDictionary = new Dictionary<string, string>();
XDocument doc = XDocument.Load("DnsServerList.xml");
if (doc.Root != null)
{
var keyValueXml = from c in doc.Root.Descendants("Dns")
select new
{
name = c.Element("Name").Value,
value = c.Element("Value").Value
};
foreach (var info in keyValueXml)
{
_nameValueDictionary.Add(info.name, info.value);
}
cmbDns.DisplayMember = "Key";
cmbDns.ValueMember = "Value";
cmbDns.DataSource = _nameValueDictionary.ToArray();
}
}
I hope it helps.

Categories

Resources