2013-09-05 49 views
5

aşağıdaki düşünün eşlemek için bir liste kopyalama: Bir haritaya list_A tüm unsurları kopyalamak istediğiniz C++ std

struct A 
{ 
    int i; 
    double d; 
    std::string s; 
}; 

std::list<A> list_A; 

haritasında her çifti olarak list_A bir elemanın oluşacaktır şekilde değer ve dize s anahtar olarak. Bunu yapmanın bir yolu var mıdır, listeden geçmekten daha zarif ve her bir unsuru, haritanın anahtarı olarak dizgisiyle birlikte ekleyelim mi?

+5

Benim için döngü, en iyi okunabilir ve en desteklenebilir çözümdür. –

+1

['std :: transform'] ile bir şeyler yapabilirsiniz (http://en.cppreference.com/w/cpp/algorithm/transform). – juanchopanza

+0

Standart "for" veya "ranged-based for" döngüsünü kullanabilirsiniz. Bunun yerine standart bir kütüphane algoritması kullanırsanız, aynı döngü gövdesini yazacak ve bir işlev nesnesine veya lambdaya algoritma geçireceksiniz. Şahsen, bu kadar basit bir şey için bir "menzile dayalı" döngüsünün "daha iyi" olduğunu düşünüyorum. – Blastfurnace

cevap

6

Bu size transform nasıl kullanılacağına ilişkin bir fikir sahibi olmalıdır:

std::pair<std::string, A> pairify(const A& a) { return std::make_pair(a.s, a); } 

std::transform(list.begin(), list.end(), std::inserter(map, map.end()), pairify); 

reason to use the inserter geçerli:

bir ekleme interator algoritmaları sağlayacak şekilde tasarlanmıştır çıktı Yineleyici özel bir türüdür genellikle, öğelerin (kopya gibi) üzerine, yeni öğeleri kabın içinde belirli bir konuma otomatik olarak yerleştirecek şekilde üzerine yazar.

+0

Ve iyi çalışıyor :) –

+0

I verimlilik hakkında soru sormadığımı biliyorum ama yine de merak ediyorum: Bu yol aynı zamanda tüm elemanlar arasında geçiş yapmaktan ve onları haritaya yerleştirmekten daha mı verimli? – Subway

1

Üzgünüz, son kez detaylı bilgi edinme zamanı çok hızlı bir şekilde cevaplandırıldı, derlenebilir bir kod.

struct A 
{ 
    int i; 
    double d; 
    std::string s; 
}; 

std::list<A> list_A; 

std::pair<std::string, A> convert(const A &x) { 
    return make_pair(x.s,x); 
} 

int main() { 

    std::map<std::string,A> out; 

    std::transform(list_A.begin(), list_A.end(), std::inserter(out,out.end()),convert); 

} 
+0

Hayır ... İlk olarak, harita iki şablon parametresine ihtiyaç duyar ve ikincisi haritanın aynı boyutuna sahip olacak şekilde haritayı başlatamazsınız. – LarryPel

+0

Ayrıca, dönüşüm aşağıdaki gibi bir şey yapacaktır: * map_iterator = functionToCopyStructToList(); ve bu şekilde bir harita yineleyici atayamazsınız ... bu kod derlenmeyecektir – LarryPel

+0

İkiniz de haklısınız, ilk kez tüm ayrıntıları olmadan ilk taslağı veriyordum – jayadev

0

Ben set depolamak olabilir: Bu şekilde (ler kendisi), haritanın veri çoğaltma olmaz:

struct A 
{ 
    bool operator < (const A& r_) const { return (s < r_.s); } 
    int i; 
    double d; 
    std::string s; 
}; 

std::list<A> list_A; 
std::set<A> set_A; 

for (std::list<A>::const_iterator itr = list_A.begin(); itr != list_A.end(); ++itr) { 
    if (! set_A.insert(*itr).second) { 
     // Handle duplicated elements 
    } 
} 

ben döngü devam edebilir: bu şekilde size kaldırabileceğinden yinelenen öğeleri doğru şekilde.

0

C++ 11 yakalama ile lambda işlevini kullanabilirsiniz kullanıyorsanız:

std::map<std::string, A> m; 
std::list<A> l; 
std::for_each(l.begin(), l.end(), 
       [&](const A& a) { 
        m.insert(std::make_pair(a.s, a)); 
       }); 
4

Ben standart kütüphane algoritmaları ve lambdas seviyorum ama almaz çok daha basit daha:

for (const A& value : list_A) { 
    map_A.insert(std::make_pair(value.s, value)); 
} 

Diğer yöntemler bu kodun eşdeğerini yapıyor ve bu döngü okunabilir ve aynı derecede hızlı.

+0

Bence bu adam basitlik için değil :). –